Java實現HTTP協議:數據包格式概覽

我們看看http協議的數據包格式,首先可以使用wireshark抓包,由於http協議使用80端口,因此可以在wiresharks中使用過濾條件tcp.prot==80,然後用瀏覽器打開一個頁面,在wireshark裏會看到這樣的抓包:
屏幕快照 2020-04-17 下午5.44.59.png
雙擊打開會看到如下內容,這就是http協議的主要內容和結構:
屏幕快照 2020-04-17 下午5.50.41.png
下面我們對其內容進行詳細解讀。HTTP數據包遵守以下基本格式:
<起始行>
<消息頭>
<空白行>
<消息體>
<消息尾>
要注意的是每一行都必須以/r/n結尾。起始行就是上圖中被選中的那行"HTTP1.1 204 No Centent\r\n",如果數據包是客戶端對服務器的請求,那麼起始行就會包含數據請求的方法,數據在服務器上的位置,如果是服務器回覆給客戶端的數據包,起始行就包含請求的狀態,後面我們會詳細分析起始行的內容。

接下來是消息頭,它以key-value的方式組織,通常爲:,消息體其實是可選項,如果服務器告知客戶端請求失敗,那麼消息體就包含失敗的具體原因,如果請求成功,那麼消息體就包含要傳遞給客戶端的數據內容。由於HTTP1.1要求保持持久連接,於是數據有可能通過多個數據包傳遞,這樣就需要對消息體進行標記,用來說明那些消息體裏面的內容屬於同一個整體。通常情況下會有一個特別字段指明消息的長度,也就是圖中的content-Length,如果所有的數據傳輸完畢,在最後一個數據包還會有消息尾,消息尾和頭結構基本上一樣。

客戶端發送給服務器的數據包裏,第一行叫請求行。它包含三個目的,第一是表明請求的來意;第二,指明請求對應資源所在位置;第三,告訴服務器採用哪個版本的HTTP協議。因此請求行的基本結構就是<方法><請求資源URI><HTTP版本>,例如一個具體例子的請求行爲: GET /index.html HTTP/1.1,它表示客戶端想獲取數據,數據的地址就是位於當前根目錄下的index.html,雙方使用HTTP/1.1版本的協議進行交互。其中<方法>真的的是服務器,它告訴服務器應該怎麼做,注意它一定要使用大寫字母。在1.1版本的協議中,常用方法有GET,HEAD,POST,這些方法的具體內容我們在後續章節中還要深入解析。

請求行中的<請求資源URI>對應瀏覽器去掉域名後的那部分內容。例如當瀏覽器中輸入內容爲"http://www.mysize.com:8080/chatware/chatroom.php",那麼對應的資源URI就是"/chatware/chatroom.php",那麼在消息頭中就可能包含這句"Host:www.mysize.com:8080"。情況也有例外,如果是代理服務器收到該請求時,他必須把整個URL當成URI轉發給下一個服務器。

最後的協議版本會讓服務器決定如何與客戶端保持連接。如果是0.9或1.0版本,服務器在發送完數據後會自己將TCP連接給斷掉,如果是1.1版本,那麼服務器就會保持着與客戶端的連接。

接下來看header部分,它也叫頭部,這部分進一步告訴服務器請求的詳細信息。頭部信息根據作用不同也分成不同種類。一種叫廣義頭部,這種頭部表述的內容與客戶端要請求的資源無關,但與如何處理當前消息有關,它主要用來給服務器提供更多有關當前消息數據包的信息。第二種叫請求頭部,它用來詳細指導服務器如何處理當前請求,例如告訴服務器如何編碼客戶端所請求的資源等。第三種叫實體頭部,他用來告訴服務器返回的數據包中應該包含哪種信息,頭部部分會在後續章節中詳細解讀。

接下來看服務器的返回數據包格式,其大體結構如下:
<狀態行>
<廣義頭部>
<回覆頭部>
<空行>
[<消息體>]
[<消息尾>]
狀態行用來告訴客戶端服務器支持什麼版本的協議,請求處理的結果等,狀態行的基本格式爲<協議版本><狀態碼><狀態碼說明>,我們看一個具體例子:

屏幕快照 2020-04-18 上午10.49.39.png

其中第一行就是狀態行,它表示服務器支持版本1.1 狀態碼和接下來的”OK“表明請求成功,下面粉色部分是消息體,它在回覆數據包中可有可無。在服務器的回覆數據包中肯定包含頭部部分,它的類型與客戶端數據包的頭部部分一樣。如果回覆數據包中包含消息體的話,那麼這部分基本上對應客戶端要請求的資源內容。

下一小節我們隊HTTP數據包中的請求方法及其作用做詳細的解析。

更詳細的講解和代碼調試演示過程,請點擊鏈接

更多技術信息,包括操作系統,編譯器,面試算法,機器學習,人工智能,請關照我的公衆號:
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章