HTTPweb伺服器 HTTP整體設計框架

2021-07-31 00:03:19 字數 2888 閱讀 7459

我們整個的專案採用b/s模式,通過瀏覽器傳送http的get方法和post方法,然後server進行響應,這樣最終通過html看到我們所顯示的最終的效果。

另外,為了支援併發,我們採用了多執行緒的結構。

和其他socket程式設計的模式是一樣的,我們這裡的第一步依然是首先建立監聽套接字,建立的過程依然是,

socket–>bind—>listen。

這裡在bind的時候採用sockaddr_in方式,另外為了實現埠的復用,我們採用了setsockopt的su_reuseaddr方式。

listen的時候,我們這裡經常需要關注backlog,這個是已完成佇列和未完成佇列和的大小。

我們進行accept接收客戶端的connect請求。這個過程的實質是對backlog佇列的乙個操作,在accept前,核心接受到connect請求首先把socket放入未完成佇列,然後accept的時候,需要把socket放入已完成佇列當中去,然後accept成功以後從已完成佇列當中取出。這就是accept的整個過程。

在整個執行緒處理函式內部,我們對http的請求進行分析,通過對其中的路徑引數等資訊,我們呼叫根目錄下的index.html進行處理。

執行緒處理中,少不了的就是對http報文資訊的處理,從這些中提取出來有用的資訊,我們採取的讀取方式是按行讀取。

例如對http 方法的第一行進行讀取,然後這一行的三個欄位又是按照空格隔開,我們利用這個特性,把http請求的方法(get或post,目前只進行處理這兩個),然後可以得到資源路徑(url),最後乙個欄位是http 的版本資訊。

得到這一部分資源以後,我們現在就需要進行處理,接下來就是考慮引數。http請求經常會帶一些引數,通過這些引數瀏覽器請求資源,get方法的資源是在url當中,post方法的資源是在訊息正文當中,這樣我們也就能得到資源了。

引數的形式一般為:

所以這裡需要說的是,其實我們的多執行緒http伺服器總共會有三種情況:

情況說明

非cgi

此時不帶引數,我們需要返回主頁給瀏覽器

get cgi

此時引數在url後,並且按照一定的規律連線,我們需要把引數提出來交給cgi程式去進行運算

post cgi

此時引數在訊息正文當中,我們需要結合訊息報頭,提取引數

我們這裡先來看下非cgi方式,這種情況下,首先明白此時我們可以得到資源路徑,這個資源路徑其實就是根目錄下的路徑,預設我們去尋找根目錄下的主頁。

所以我們需要給資源加上index.html

然後我們把整個index.html的資訊傳送給scoket。

我們在這裡採用的方式是sendfile的操作,sendfile主要是實現零拷貝傳送檔案,實現乙個高效的資料傳輸,並且對其進行驗證。這樣socket接受到主頁資訊,就可以顯示出來網頁了,當然這個過程我們也是按照httppost響應傳送過去的。

cgi模式是我們操作的一種方式,這種方式下我們處理帶引數的http請求,我們把這些引數都取出來,然後把這些引數使得cgi程式能夠獲取到,獲取到以後就可以進行計算或者資料處理等。

具體框架如圖。

在這裡我們的處理方式就是對這兩組管道需要進行一下重定向,對於fork以後的子程序,我們把管道重定向,利用dup2系統呼叫,然後達到的效果就是子程序最終可以從stdin中得到父程序給的資訊,而父程序也就是伺服器又可以從socket得到http請求的內容。然後子程序資料計算以後把資料寫到stdout中,server從管道中取回資料,傳送給socket。這樣socket端也就是瀏覽器那邊就可以顯示出最後的結果。

在這個裡面重要的還有乙個點就是http的引數如何傳遞到cgi程式當中。下面我們分開來說一下。這裡我們使用的是環境變數的方式,cgi程式在子程序當中執行,可以獲取到環境變數,所以就可以得到所需要的引數,具體看下面的介紹。

get方法的時候,這個時候cgi所需要的引數是放在url當中的,所以這個時候我們就去在http get請求行的第二個內容資源路徑當中進行字串的處理,我們找『?』,當找到以後,我們讓乙個指標指向這裡,叫做query_string,我們把這個作為乙個環境變數傳遞給子程序就可以了。對於get的cgi模式,最重要的也就是method(方法)和query_string(包含引數)

但是當我們使用post方法的cgi模式的時候,這個時候就會有另外的問題,我們的引數在正文當中,所以我們需要在正文當中尋找,另外需要知道正文中的位元組數。這個時候post的訊息報頭就起作用了,它在其中阻止了name:value形式的content_length:xx這樣的內容,然後獲取到這個長度以後,我們就可以知道向socket讀取多少長度的內容了,然後讀取完以後我們就可以獲得到引數,同樣是按照「?」和「&」的形式進行組織的,我們取出這個內容,然後進行資料運算操作。

我們需要說一下父程序的後續操作,父程序進行處理的時候首先需要重定向管道,這樣才好進行後續的操作,然後我們進行檢視方法,如果是post方法,我們需要把http的請求正文全部獲取到放入和cgi程式打交道的管道當中。這樣才能讓cgi獲取到正文資訊,其他情況下,我們都需要從cgi返回到管道的結果當中進行獲取返回的資訊,把這個資訊傳送給socket。最後,當然別忘了使用waitpid等待子程序。

cgi的編寫方式我們可以叫做cgi閘道器協議,我們所有的cgi程式都可以套用這一套來進行操作,我們採用的傳遞引數方式是環境變數,其實還可以用管道進行傳遞,傳遞進管道,cgi程式從管道當中讀取出來。

然後我們進行字串處理。

因為引數的組織形式是」?data1=100&data2=200」這種形式的,所以我們要找的關鍵符號就是「=」和「&」,這樣我們就可以取到引數,然後把引數進行運算,得到結果輸出到標準輸出就好了。

我們的cgi操作形式其實是可以多種多樣的,我們可以提供math計算操作,也可以提供關於對資料庫mysql的操作,另外,我們也可以去操作我們使用python爬蟲爬下來的資料來進行操作,後續比如也可以在html上面跑乙個日期類,顯示下天氣等資訊。

C Socket實現Http WEB伺服器

c socket實現http web伺服器 2010年03月22日 www的工作基於客戶機 伺服器計算模型,由web 瀏覽器 客戶機 和web伺服器 伺服器 構成,兩者之間採用超文字傳送協議 http 進行通訊,http協議的作用原理包括四個步驟 連線,請求,應答。根據上述http協議的作用原理,本...

搭建http伺服器

本節以中標麒麟桌面作業系統 龍芯版 為例,簡單介紹 http伺服器搭建方法,其他作業系統或搭建 ftp 伺服器,請參考相關使用者手冊或網路資料。1.在 var www html 下建立update,再在update下建立packages 和repodata。將軟體包拷貝到 var www html ...

搭理http伺服器

由於在某些特定場景下,我們的外網訪問會受到限制,如果有一些訪問需求的話就需要乙個 作為中轉了。首先需要一台機器作為中轉的伺服器,這時候當然要去阿里雲買一台啦微笑。作業系統一定要選linux,我使用的是centos。之後的主要目標是在這台機器上搭建乙個http 了。當然肯定不可能自己從頭開始寫,用現有...