專案 HTTP伺服器框架分析(一)

2021-08-28 15:19:58 字數 3937 閱讀 3984

專案:http伺服器框架分析(二)

專案:http伺服器框架**分析(三)

0、專案描述

專案名稱:基於http伺服器的~~~~專案

基於http伺服器框架的世界時間查詢器,採用多執行緒處理多客戶端連線請求,具體的還要分析請求是靜態請求還是動態請求,靜態請求直接返回對應url目錄中的html資源,動態請求使用了cgi技術處理具體業務,接收到城市名稱後,就從後台mysql資料庫中取該城市與北京時間時差,計算後將結果返回給客戶端。利用duhup執行shell指令碼實現**訪問。利用webbench測試**的併發量。

1、埠號重用機制是怎麼實現的?

只有主動關閉的一方才會進入time_wait狀態,那這種情況也就是高併發連線都是服務端主動關閉。那麼埠不夠用就是檔案描述符不夠用了,因為檔案描述符只有在從time_wait狀態轉換到close狀態後才會真正被系統收回。time_wait狀態會持續2msl的時間才會轉換到close狀態,一般是1-4分鐘。如果在這段時間內檔案描述符都被用完了,而關閉的連線處於time_wait狀態導致檔案描述符並沒有被真正釋放,就會出現這種情況。

time_wait 狀態到底會占用什麼?

被占用的是乙個五元組:(協議,本地ip,本地埠,遠端ip,遠端埠)。對於 web 伺服器,協議是 tcp,本地 ip 通常也只有乙個,本地埠預設的 80 或者 443。只剩下遠端 ip 和遠端埠可以變了。如果遠端 ip 是相同的話,就只有遠端埠可以變了。這個只有幾萬個,所以當同一客戶端向伺服器建立了大量連線之後,會耗盡可用的五元組導致問題。

等待 time_wait 結束可能是令人惱火的一件事,特別是如果您正在開發乙個套接字伺服器,就需要停止伺服器來做一些改動,然後重啟。幸運的是,有方法可以避開 time_wait 狀態。可以給套接字應用 so_reuseaddr 套接字選項,以便埠可以馬上重用。

在繫結位址之前,以 so_reuseaddr 選項呼叫 setsockopt。為了允許位址重用,設定整型引數(on)為 1 (不然,可以設為 0 來禁止位址重用)。

on = 1; 

ret = setsockopt( sock, sol_socket, so_reuseaddr, &on, sizeof(on) );

2、accept多執行緒建立過程?

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

執行緒分離

pthread_detach(pthread_t thread)

而pthread_join(執行緒id,二級指標,指向乙個執行緒的返回值)

不關心執行緒返回值,join是一種負擔。

3、怎麼寫乙個shell指令碼、duhup?

4、狀態碼有哪些?

(1)100:繼續 客戶端應當繼續傳送請求。客戶端應當繼續傳送請求的剩餘部分,或者如果請求已經完成,忽略這個響應。

(2)200: 請求成功。

(3)201:請求完成,結果是建立了新資源。

(4)301:請求到的資源都會分配乙個永久的url。這樣就可以在將來通過該url來訪問此資源 處理方式:重定向到分配的url。

(5)302:請求到的資源在乙個不同的url處臨時儲存。處理方式:重定向到臨時的url。

(6)400:非法請求 處理方式:丟棄。

(7)401:未授權 處理方式:丟棄。

(8)404:沒有找到 處理方式:丟棄。

(9)500:伺服器內部錯誤。

(10)501:伺服器無法識別 伺服器不支援當前請求所需要的某個功能。

(11)503:服務出錯 由於臨時的伺服器維護或者過載,伺服器當前無法處理請求。

5、非cgi模式流程?

首先明白此時我們可以得到資源路徑,這個資源路徑其實就是根目錄下的路徑,預設我們去尋找根目錄下的主頁。

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

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

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

6、cgi模式流程?

cgi優點:解耦合

cgi缺點:每次出發cgi都要建立子程序,高併發導致伺服器效能降低。

1、建立一對匿名管道;

2、建立子程序;

3、父程序等待子程序返回;

7、get模式的cgi?

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

8、post模式的cgi?

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

9、父程序的後序操作?

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

怎麼等待子程序?

如果用wait(null)是不行的,wait是無差別等待,見到任意子程序就**,造成資源**錯亂,等待任意子程序。waitpid(child_pid, null, 0)函式指定了子程序pid。

10、cgi邏輯中父子程序讀寫的細節問題?

邏輯流程偽**:

int handlercgi(int new_sock, request *req)

else if(ret == 0)

else

}

在處理父程序的cgi時,關閉子程序讀寫端,為了父程序從子程序中讀取資料的時候,能夠讀到eof。對於管道來說,所有寫端關閉,繼續讀才有eof。

11、cgi的編寫方式?

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

然後我們進行字串處理。

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

12、專案拓展性問題?

1、為了實現高併發,可以使用高階i/o,使用poll、epoll形式等待就緒檔案描述符。

2、業務邏輯的拓展:利用python爬取一些**資料,然後對資料進行處理。比如每天爬取天氣預報,使用者註冊之後,每天定時將天氣資訊通過郵箱傳送給使用者。

3、cgi是一種古老動態頁面生成方式,只要有乙個客戶端觸發,就要建立子程序,高併發環境下,建立子程序開銷比較大,建議使用其他的組織方式。

專案二 HTTP伺服器

專案二 http伺服器 在學習servlet技術和使用tomcat之前,熟悉其底層基本原理。http伺服器採用請求 響應模式,即乙個請求對應乙個響應。本篇部落格將介紹該項目的基本思路,具體實現 可訪問博主的github 工欲善其事,必先利其器。需掌握 1 掌握http協議 2 掌握io流 3 網路程...

HTTP伺服器專案詳解

http 伺服器專案 功能 用到的技術 開發環境 注意 關於http的一些基礎知識我就不談了,有興趣可以自行了解 接下來,我就分模組的介紹一下我的專案吧 模組化介紹 socketapi 模組 入口處理模組 處理請求模組 響應處理模組 cgi 模組 執行緒池模組 專案的問題 web伺服器專案原始碼 因...

HTTP伺服器專案過程

一 http 請求的解析 行的解析 頭的解析 二 http響應的組裝 行的組裝 頭的組裝 體的組裝 三 serversocket socket 建立連線 四 靜態的controller 1.根據url獲取真實的檔案路徑 2.根據檔名字尾,獲取content type 3.賦值檔案內容到respons...