TCP通信流程解析(以訪問一次百度網站為例)(包括以太網幀頭、IP頭、TCP頭、UDP頭)


B/S通信簡述
整個計算機網絡的實現體現為協議的實現,TCP/IP協議是Internet的核心協議,HTTP協議是比TCP更高層次的應用層協議。

HTTP(HyperText Transfer Protocol,超文本傳輸協議)是互聯網上應用最為廣泛的一種網絡協議。所有的WWW文件都必須遵守這個標准。設計HTTP的初衷是為了提供一種發布和接收HTML頁面的方法。

瀏覽器(Web Browser)負責與服務器建立連接,下載網頁(包括資源文件及JS腳本文件)到本地,並最終渲染出頁面。JS腳本文件運行在客戶端,負責客戶端一些行為響應或預處理,例如提交表單前的數據校驗、鼠標事件處理等交互。由此可見,瀏覽器(Browser)一方面充當了C/S通信架構中C角色,另一方面它是HTML/JavaScript的解析渲染引擎(Analyze Render Engine)。

當在瀏覽器地址欄敲入“http://www.baidu.com/”並按下回車鍵時,瀏覽器中將呈現出百度搜索引擎首頁。這樣一種情景我們再熟悉不過,本文通過wireshark抓取這一過程的數據包,結合TCP協議分析HTTP通信的基本流程。

IP & MTU
本文用到的抓包工具為wireshark,它的前身是赫赫有名的Ethereal。wireshark以太網幀的封包格式為:

----------------------------------------------------------------------------------------------------

Frame=Ethernet Header +IP Header +TCP Header +TCP Segment Data

----------------------------------------------------------------------------------------------------

(1)Ethernet Frame =Dst Physical Address(6 Byte)+ Src Physical Address(6 Byte)+Type(2 Byte)+data(46~1500 Byte)+FCS(4 Byte),以太網幀頭以下稱之為數據幀。

(2)IP Header =20 Byte(without options field),數據在IP層稱為Datagram,分片稱為Fragment。

(3)TCP Header = 20 Byte(without options field),數據在TCP層稱為Stream,分段稱為Segment(UDP中稱為Message)。

(4)54個字節后為TCP數據負載部分(Data Portion),即應用層用戶數據。

Ethernet Header以下的IP數據報最大傳輸單位為MTU(Maximum Transmission Unit,Effect of short board),對於大多數使用以太網的局域網來說,MTU=1500。

以太網幀頭:

Ethernet_II的幀中各字段說明如下:
1.DMAC(DestinationMAC)是目的MAC地址。DMAC字段長度為6個字節,標識幀的接收者。
2.SMAC(SourceMAC)是源MAC地址。SMAC字段長度為6個字節,標識幀的發送者。
3.類型字段(Type)用於標識數據字段中包含的高層協議,該字段長度為2個字節。
類型字段取值為0x0800的幀代表IP協議幀;類型字段取值為0806的幀代表ARP協議幀。
0x8847 多協議標簽交換(單播) MPLS:Multi-Protocol Label Switching <unicast>)
0x88CC 鏈接層發現協議(LLDP:Link Layer Discovery Protocol)
0x8863 以太網上的 PPP(發現階段)(PPPoE:PPP Over Ethernet <Discovery Stage>)
4.數據字段(Data)是網絡層數據,最小長度必須為46字節以保證幀長至少為64字節,數據字段的最大長度為1500字節。
5.循環冗余校驗字段(FCS)提供了一種錯誤檢測機制。該字段長度為4個字節。

 

IP頭:

 

 

 

(1)版本 占4位,指IP協議的版本。通信雙方使用的IP協議版本必須一致。廣泛使用的IP協議版本號為4(即IPv4)。關於IPv6,還處於草案階段。
(2)首部長度 占4位,可表示的最大十進制數值是15。請注意,這個字段所表示數的單位是32位字長(1個32位字長是4字節),因此,當IP的首部長度為1111時(即十進制的15),首部長度就達到60字節。當IP分組的首部長度不是4字節的整數倍時,必須利用最后的填充字段加以填充。因此數據部分永遠在4字節的整數倍開始,這樣在實現IP協議時較為方便。首部長度限制為60字節的缺點是有時可能不夠用。但這樣做是希望用戶盡量減少開銷。最常用的首部長度就是20字節(即首部長度為0101),這時不使用任何選項。
(3)區分服務 占8位,用來獲得更好的服務。這個字段在舊標准中叫做服務類型,但實際上一直沒有被使用過。1998年IETF把這個字段改名為區分服務DS(Differentiated Services)。只有在使用區分服務時,這個字段才起作用。
(4)總長度 總長度指首部和數據之和的長度,單位為字節。總長度字段為16位,因此數據報的最大長度為2^16-1=65535字節。
在IP層下面的每一種數據鏈路層都有自己的幀格式,其中包括幀格式中的數據字段的最大長度,這稱為最大傳送單元MTU(Maximum Transfer Unit)。當一個數據報封裝成鏈路層的幀時,此數據報的總長度(即首部加上數據部分)一定不能超過下面的數據鏈路層的MTU值。
(5)標識(identification) 占16位。IP軟件在存儲器中維持一個計數器,每產生一個數據報,計數器就加1,並將此值賦給標識字段。但這個“標識”並不是序號,因為IP是無連接服務,數據報不存在按序接收的問題。當數據報由於長度超過網絡的MTU而必須分片時,這個標識字段的值就被復制到所有的數據報的標識字段中。相同的標識字段的值使分片后的各數據報片最后能正確地重裝成為原來的數據報。
(6)標志(flag) 占3位,但只有2位有意義。
● 標志字段中的最低位記為MF(More Fragment)。MF=1即表示后面“還有分片”的數據報。MF=0表示這已是若干數據報片中的最后一個。
● 標志字段中間的一位記為DF(Don’t Fragment),意思是“不能分片”。只有當DF=0時才允許分片。
(7)片偏移 占13位。片偏移指出:較長的分組在分片后,某片在原分組中的相對位置。也就是說,相對用戶數據字段的起點,該片從何處開始。片偏移以8個字節為偏移單位。這就是說,除了最后一個分片,每個分片的長度一定是8字節(64位)的整數倍。
(8)生存時間 占8位,生存時間字段常用的的英文縮寫是TTL(Time To Live),表明是數據報在網絡中的壽命。由發出數據報的源點設置這個字段。其目的是防止無法交付的數據報無限制地在因特網中兜圈子,因而白白消耗網絡資源。最初的設計是以秒作為TTL的單位。每經過一個路由器時,就把TTL減去數據報在路由器消耗掉的一段時間。若數據報在路由器消耗的時間小於1秒,就把TTL值減1。當TTL值為0時,就丟棄這個數據報。后來把TTL字段的功能改為“跳數限制”(但名稱不變)。路由器在轉發數據報之前就把TTL值減1.若TTL值減少到零,就丟棄這個數據報,不再轉發。因此,TTL的單位不再是秒,而是跳數。TTL的意義是指明數據報在網絡中至多可經過多少個路由器。顯然,數據報在網絡上經過的路由器的最大數值是255.若把TTL的初始值設為1,就表示這個數據報只能在本局域網中傳送。
(9)協議 占8位,協議字段指出此數據報攜帶的數據是使用何種協議,以便使目的主機的IP層知道應將數據部分上交給哪個處理過程。
(10)首部檢驗和 占16位。這個字段只檢驗數據報的首部,但不包括數據部分。這是因為數據報每經過一個路由器,路由器都要重新計算一下首部檢驗和(一些字段,如生存時間、標志、片偏移等都可能發生變化)。不檢驗數據部分可減少計算的工作量。
(11)源地址 占32位。
(12)目的地址 占32

Options(可選項):是一個長度可變的字段。它是可選的。
可選項如下:
 松散源路由選擇(loose source routing給出了一連串路由器接口的IP地址序列。數據包必須沿着IP地址序列傳送,但是允許相繼的2個地址之間可跳過多台路由器。
 嚴格源路由選擇(strict source routing也給出了一連串路由器接口的IP地址序列,不同於松散源路由選擇的是,數據包必須按照路由轉發。如果下一條不在路由表,就將會發生錯誤。
 記錄路由(Record Router當數據包離開時為每台路由器提供空間記錄數據包的出站接口地址。
 時間戳(timestamp:時間戳相當於路由記錄選項,這樣數據包不僅可以知道自己到過那里。而且還可以記錄到達的時間。
填充(padding)在可選項后面添加0來補足32位,主要是保證報頭是32位的倍數

 

TCP數據包每次能夠傳輸的最大數據分段為MSS(Maximum Segment Size)。

為了達到最佳的傳輸效能,在建立TCP連接時雙方將協商MSS值——雙方提供的MSS值中的最小值為這次連接的最大MSS值。

MSS往往基於MTU計算出來,通常 MSS = MTU-sizeof(IP Header)-sizeof(TCP Header)=1500-20-20=1460。

這樣,數據經過本地TCP層分段后,交給本地IP層,在本地IP層就不需要分片了。但是在下一跳路由(Next Hop)的鄰居路由器上可能發生IP分片!因為路由器的網卡的MTU可能小於需要轉發的IP數據報的大小。這時候,在路由器上可能發生兩種情況:

(1)如果源發送端設置了這個IP數據包可以分片(May Fragment,DF=0),路由器將IP數據報分片后轉發。

(2)如果源發送端設置了這個IP數據報不可以分片(Don’t Fragment,DF=1),路由器將IP數據報丟棄,並發送ICMP分片錯誤消息給源發送端。

關於MTU的探測,參考《Path MTU discovery》。我們可以通過基於ICMP協議的ping命令來探測從本機出發到目標機器上路由上的MTU,詳見下文。

TCP & MSS
下圖是 TCP 報文格式:

 

 

 

    16位端口號:告知主機該報文段是來自哪里(源端口Source Port)以及傳給哪個上層協議或應用程序(目的端口Destination Port)的。進行TCP通信時,客戶端通常使用系統自動選擇的臨時端口號,而服務器則使用知名服務端口號(比如DNS協議對應端口53,HTTP協議對應80,這些端口號可在/etc/services文件中找到)。

        32位序號:一次TCP通信(從TCP連接建立到斷開)過程中某一個傳輸方向上的字節流的每個字節的編號。假設主機A和主機B進行TCP通信,A發送給B的第一個TCP報文段中,序號值被系統初始化為某個隨機值ISN(Initial Sequence Number,初始序號值)。那么在該傳輸方向上(從A到B),后續的TCP報文段中序號值將被系統設置成ISN加上該報文段所攜帶數據的第一個字節在整個字節流中的偏移。例如,某個TCP報文段傳送的數據是字節流中的第1025~2048字節,那么該報文段的序號值就是ISN+1025.另外一個傳輸方向(從B到A)的TCP報文段的序號值也具有相同的含義。

        32位確認號(acknowledgement number):用作對另一方發送來的TCP報文段的響應。其值是收到的TCP報文段的序號值加1。假設主機A和主機B進行TCP通信,那么A發送出的TCP報文段不僅攜帶自己的序號,而且包含對B發送來的TCP報文段的確認號。反之,B發送出的TCP報文段也同時攜帶自己的序號和對A發送來的報文段的確認號。

        4位頭部長度(header length):標識該TCP頭部有多少個32bit字(4字節)。因為4位最大能標識15,所以TCP頭部最長是60字節。

        6位標志位包含如下幾項:

        URG標志,表示緊急指針(urgent pointer)是否有效。

        ACK標志,表示確認號是否有效。我們稱攜帶ACK標識的TCP報文段為確認報文段。

        PSH標志,提示接收端應用程序應該立即從TCP接收緩沖區中讀走數據,為接收后續數據騰出空間(如果應用程序不將接收

        到的數據讀走,它們就會一直停留在TCP接收緩沖區中)。

         RST標志,表示要求對方重新建立連接。我們稱攜帶RST標志的TCP報文段為復位報文段。

         SYN標志,表示請求建立一個連接。我們稱攜帶SYN標志的TCP報文段為同步報文段。

         FIN標志,表示通知對方本端要關閉連接了。我們稱攜帶FIN標志的TCP報文段為結束報文段。

       16位窗口大小(window size):是TCP流量控制的一個手段。這里說的窗口,指的是接收通告窗口(Receiver Window,RWND)。它告訴對方本端的TCP接收緩沖區還能容納多少字節的數據,這樣對方就可以控制發送數據的速度。此值告訴發送方,在沒有收到我的確認時,你可以發送的數據的字節數最多是這個數值。

        16位校驗和(TCP check sum):由發送端填充,接收端對TCP報文段執行CRC算法以檢驗TCP報文段在傳輸過程中是否損壞。注意,這個校驗不僅包括TCP頭部,也包括數據部分。這也是TCP可靠傳輸的一個重要保障。

        16位緊急指針(urgent pointer):是一個正的偏移量。它和序號字段的值相加表示最后一個緊急數據的下一字節的序號。因此,確切地說,這個字段是緊急指針相對當前序號的偏移,不妨稱之為緊急偏移。TCP的緊急指針是發送端向接收端發送緊急數據的方法。

        TCP頭部選項:TCP頭部的最后一個選項字段(options)是可變長的可選信息。這部分最多包含40字節,因為TCP頭部最長是60字節(其中還包含前面討論的20字節的固定部分)。典型的TCP頭部選項結構如下圖所示。

在基於傳輸層(TCP/UDP)的應用開發中,為了最后的程序優化,應避免端到端的任何一個節點上出現IP分片。TCP的MSS協商機制加上序列號確認機制,基本上能夠保證數據的可靠傳輸。

UDP
下圖是 UDP 報文格式:

 

 

 

UDP協議在IP協議的基礎上,只增加了傳輸層的端口(Source Port+Destination Port)、UDP數據包長(Length = Header+Data)以及檢驗和(Checksum)。因此,基於UDP開發應用程序時,數據包需要結合IP分片情況考慮。對於以太局域網,往往取UDP數據包長Length<=MTU-sizeof(IP Header)=1480,故UDP數據負載量小於或等於1472(Length-UDP Header);對於公網,ipv4最小MTU為576,UDP數據負載量小於或等於548。

“向外”NAT在內網和公網之間提供了一個“不對稱”橋的映射。“向外”NAT在默認情況下只允許向外的session穿越NAT:從外向內的的數據包都會被丟棄掉,除非NAT設備事先已經定義了這些從外向內的數據包是已存在的內網session的一部分。對於一方在LAN,一方在WAN的UDP通信,鑒於UDP通信不事先建立虛擬鏈路,NAT后面的LAN通信方需先發送消息給WAN通信方以洞穿NAT,然后才可以進行雙向通信,這即是常提到的“UDP打洞(Hole Punching)”問題。

TCP連接百度過程解析
1.wireshark抓包
下文對百度的完整抓包建立在不使用緩存的基礎上。如若主機存有百度站點的cookie和脫機緩存(Offline Cache),則不會再請求地址欄圖標favicon.ico;請求/js/bdsug.js?v=1.0.3.0可能回應“HTTP/1.1 304 Not Modified”。可在瀏覽器打開百度首頁后,Ctrl+F5強制刷新,不使用緩存,也可參考《瀏覽器清除緩存方法》。

以下為訪問百度過程,wireshark抓包數據。對於直接通過Ethernet聯網的機器,Wireshark Capture Filter為"host www.baidu.com";對於通過PPP over Ethernet(PPPoE)聯網的機器,Wireshark Capture Filter為"pppoes and host www.baidu.com"。以下抓包示例直接通過Ethernet聯網訪問百度的過程。可點擊下面的圖片超鏈接下載pcap文件,使用wireshark軟件打開查看。

為方便起見,以下將客戶端(瀏覽器)簡稱為C,將服務器(百度后台)簡稱為S。

 

 

 

2.TCP三次握手建立連接
“http://”標識WWW訪問協議為HTTP,根據規則,只有底層協議建立連接之后才能進行更高層協議的連接。在瀏覽器地址欄輸入地址后按下回車鍵的瞬間,C建立與S(機器名為www.baidu.com,DNS解析出來的IP為220.181.6.175)的TCP 80連接(HTTP默認使用TCP 80端口)。

以下為三次握手建立TCP連接的數據包(Packet1-Packet3)。

/****************************************************************************************************

1  192.168.89.125:5672→220.181.6.175:80   TCP(協議) 62(以太網幀長)

     amqp > http [SYN] Seq=0 Win=65535 Len=0 MSS=1460 SACK_PERM=1

2  220.181.6.175:80→192.168.89.125:5672 TCP 62

    http > amqp [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1460 SACK_PERM=1

3  192.168.89.125:5672→220.181.6.175:80   TCP 54

     amqp > http [ACK] Seq=1 Ack=1 Win=65535 Len=0

****************************************************************************************************/

三次握手建立TCP連接的流程如下:

    C(Browser)                                    S(www.baidu.com)

 1. CLOSED                                             LISTEN

 2. SYN-SENT    →<SEQ=0><CTL=SYN>              → SYN-RECEIVED

 3. ESTABLISHED← <SEQ=0><ACK=1><CTL=SYN,ACK> ← SYN-RECEIVED

 4. ESTABLISHED→ <SEQ=1><ACK=1><CTL=ACK>      → ESTABLISHED

 

2.1 三次握手的socket層執行邏輯
S調用socket的listen函數進入監聽狀態;C調用connect函數連接S:[SYN],S調用accept函數接受C的連接並發起與C方向上的連接:[SYN,ACK]。C發送[ACK]完成三次握手,connect函數返回;S收到C發送的[ACK]后,accept函數返回。

2.2 關於Seq和Ack
Seq即Sequence Number,為源端(source)的發送序列號;Ack即Acknowledgment Number,為目的端(destination)的接收確認序列號。在Wireshark Display Filter中,可使用tcp.seq或tcp.ack過濾。

在Packet1中,C:5672向S:80發送SYN握手包,Seq=0(relative sequence number);在Packet2中,S:80向C:5672發送ACK握手回應包,Ack=1(relative sequence number),同時發送SYN握手包,Seq=0(relative sequence number);在Packet3中,C:5672向S:80發送ACK握手回應包,Seq=1,Ack=1。

至此,Seq=1為C的ISN(Initial Sequence Number),后期某一時刻的Seq=ISN+累計發送量(cumulative sent);Ack=1為C的IAN(Initial Acknowledge Number),后期某一時刻的Ack=IAN+累計接收量(cumulative received)。對於S而言,Seq和Ack情同此理。

參考:《TCP Analyze Sequence Numbers》、《Understanding TCP Sequence and Acknowledgement Numbers》

3.TCP獲取網站數據流程
連接建立后,下一步發送(“GET / HTTP/1.1”)請求(Request)HTML頁面,這里“/”表示S的默認首頁,“GET”為HTTP Request Method;“/”為Request-URI,這里為相對地址;HTTP/1.1表示使用的HTTP協議版本號為1.1。

以下為HTTP GET請求數據包(Packet4)。

/****************************************************************************************************

4  192.168.89.125:5672→220.181.6.175:80 HTTP 417

GET / HTTP/1.1

****************************************************************************************************/

HTTP GET報文長=417-54=363個字節,其中Next sequence number: 364(relative sequence number)表示,若在規定的時間內收到S響應Ack=364,表明該報文發送成功,可以發送下一個報文(Seq=364);否則重傳(TCP Retransmitssion)。序列號確認機制是TCP可靠性傳輸的保障。

S(http)收到HTTP GET報文(共363個字節),向C(amqp)發送TCP確認報文(Packet5)。

/****************************************************************************************************

5  220.181.6.175:80→ 192.168.89.125:5672 TCP 60

http > amqp [ACK] Seq=1 Ack=364 Win=6432 Len=0

****************************************************************************************************/

這里Seq=1,為S的ISN,意為已發送過SYN。Packet2中,Ack=1為S的IAN。這里的Ack-IAN=364-1=363表示S已經從C接收到363個字節,即HTTP GET報文。同時,Ack=364也是S期待C發送的下一個TCP報文序列號(上面分析的Next sequence number)。

接下來,S向C發送Http Response,根據HTTP協議,先發響應頭(Response Header),再發百度首頁HTML文件。

Http Response Header報文(Packet6)如下。

/****************************************************************************************************

6  220.181.6.175:80→ 192.168.89.125:5672 TCP 465

[TCP segment of a reassembled PDU]

****************************************************************************************************/

其部分內容如下:

======================================

HTTP/1.1 200 OK

……

Content-Length: 2139

Content-Type: text/html;charset=gb2312

Content-Encoding: gzip

======================================

S響應C的“GET / HTTP/1.1”請求,先發送帶[PSH]標識的411個字節的Http Response Header(Packet 6)。

TCP頭部[PSH]標識置位,敦促C將緩存的數據推送給應用程序,即先處理Http Response Header,實際上是一種“截流”通知。相應C的socket調用send時在IPPROTO_TCP選項級別設置TCP_NODELAY為TRUE禁用Nagle算法可以“保留發送邊界”,以防粘連。

盡管握手協商的MSS為1460,但服務器或者代理平衡服務器,每次發送過來的TCP數據最多只有1420個字節。可以使用ping -f -l size target_name命令向指定目標target_name發送指定字節量的ICMP報文,其中-l size指定發送緩沖區的大小;-f則表示在IP數據報中設置不分片DF(Don’t Fragment),這樣便可探測出到目標路徑上的MTU。

執行“ping -f -l 1452 www.baidu.com”的結果如下:

220.181.6.18的 Ping統計信息:

   數據包:已發送 = 4,已接收 = 4,丟失 = 0 (0%丟失)

執行“ping -f -l 1453 www.baidu.com”的結果如下:

需要拆分數據包但是設置 DF。

220.181.6.18的 Ping統計信息:

   數據包:已發送 = 4,已接收 = 0,丟失 = 4 (100%丟失)

從以上ping結果可知,在不分片時,從本機出發到百度的路由上能通過的最大數據量為1452,由此推算出MTU{local,baidu}=sizeof(IP Header)+ sizeof(ICMP Header)+sizeof(ICMP Data Portion)=20+8+1452=1480。

S調用socket的send函數發送2139個字節的Http Response Content(Packet 7、Packet 9),在TCP層將分解為兩段(segment)后再發出去。

/****************************************************************************************************

7  220.181.6.175:80→ 192.168.89.125:5672 TCP 1474

[TCP segment of a reassembled PDU]

----------------------------------------------------------------------------------------------------

由“Content-Length: 2139”可知,HTML文件還有2139-(1474-54)=719個字節。但此時,C已經發送了確認報文(Packet8)。

/****************************************************************************************************

8  192.168.89.125:5672→  220.181.6.175:80 TCP 54

amqp > http [ACK] Seq=364 Ack=1832 Win=65535 Len=0

****************************************************************************************************/

Seq-ISN=364-1=363,表示C已經發出了363個字節,上邊已經收到了S的確認。Ack-IAN=1832-1=(465-54)+(1474-54),表示C至此已經接收到S發來的1831個字節。

接下來,C收到HTML文件剩余的719個字節,報文(Packet9)如下。

/****************************************************************************************************

9  220.181.6.175:80→ 192.168.89.125:5672 HTTP  773

HTTP/1.1 200 OK

****************************************************************************************************/

至此,C收到S發送過來的全部HTTP響應報文,即百度首頁HTML內容(text/html)。

Packet6、Packet7和Packet9的ACK都是364,這是因為這三個segment都是針對Packet4的TCP響應。S將百度首頁HTML文件(一個完整的HTTP報文)按照MSS分段提交給TCP層。在Wireshark中可以看到Packet9的報文中有以下reassemble信息:

[Reassembled TCP segments (2555 bytes): #6(411),#7(1420),#9(719)]

[Frame: 6, payload: 0-410(411 bytes)]

[Frame: 7, payload: 411-1830(1420 bytes)]

[Frame: 9, payload: 1831-2549(719 bytes)]

C(amqp)接收到百度首頁的HTML文件后,開始解析渲染。在解析過程中,發現頁面中含有百度的logo資源baidu_logo.gif,並且需要bdsug.js腳本。

<img src="http://www.baidu.com/img/baidu_logo.gif" width="270" height="129" usemap="#mp">

{d.write('<script src=http://www.baidu.com/js/bdsug.js?v=1.0.3.0><//script>')}

於是上面那個連接(C:5672)繼續向S請求logo圖標資源,報文(Packet10)如下。

/****************************************************************************************************

10 192.168.89.125:5672→  220.181.6.175:80 HTTP 492

GET /img/baidu_logo.gif HTTP/1.1

****************************************************************************************************/

與此同時,C(jms)新建一個連接(TCP 5673)向S請求js腳本文件。報文(Packet11)如下。

/****************************************************************************************************

11 192.168.89.125:5673→  220.181.6.175:80 TCP 62

jms > http [SYN] Seq=0 Win=65535 Len=0 MSS=1460 SACK_PERM=1

****************************************************************************************************/

(Packet12)Packet13、Packet14、Packet16和Packet17為對Packet10的TCP響應(它們的Ack=802),在邏輯上它們是一個完整的TCP報文。其Http Response Content為圖片文件baidu_logo.gif。我們在Wireshark中可以看到Packet17的報文中有以下reassemble信息:

[Reassembled TCP segments (1801 bytes): #13(312),#14(1420),#16(28) ,#17(41)]

[Frame: 13, payload: 0-311(312 bytes)]

[Frame: 14, payload: 312-1731(1420 bytes)]

[Frame: 16, payload: 1732-1759(28 bytes)]

[Frame: 17, payload: 1760-1800(41 bytes)]

Packet11-Packet19-Packet20完成新連接的三次握手。然后,C(jms)發送“GET /js/bdsug.js?v=1.0.3.0 HTTP/1.1”報文(Packet21),以獲取bdsug.js腳本文件。

/****************************************************************************************************

21 192.168.89.125:5673→  220.181.6.175:80 HTTP 465

GET /js/bdsug.js?v=1.0.3.0 HTTP/1.1

****************************************************************************************************/

(Packet22)Packet23、Packet24、Packet26和Packet27為對Packet21的TCP響應(它們的Ack=412),在邏輯上它們是一個完整的TCP報文。其Http Response Content為腳本文件bdsug.js。我們在Wireshark中可以看到Packet27的報文中有以下reassemble信息:

[Reassembled TCP segments (3897 bytes): #23(310),#24(1420),#26(1420) ,#27(747)]

[Frame: 23, payload: 0-309(310 bytes)]

[Frame: 24, payload: 310-1729(1420 bytes)]

[Frame: 26, payload: 1730-3149(1420 bytes)]

[Frame: 27, payload: 3150-3896(747 bytes)]

通常,瀏覽器會自動的搜索網站的根目錄,只要它發現了favicon.ico這個文件,就把它下載下來作為網站地址欄圖標。於是,C(amqp)還將發起“GET /favicon.ico HTTP/1.1”請求網站地址欄圖標,見報文Packet29。

4.TCP四次揮手關閉連接
經Packet28確認收到了完整的japplication/javascript文件后,鏈路1(本地端口5673)使命結束,S關閉該鏈路,進入四次揮手關閉雙向連接。

(Packet30)Packet31和Packet32為對Packet29的TCP響應(它們的Ack=1201)。經Packet33確認收到了完整的image/x-icon文件后,鏈路2(本地端口5672)使命結束,S關閉該鏈路,進入四次揮手關閉雙向連接。

   為什么握手是三次,而揮手是四次呢?這是因為握手時,服務器往往在答應建立連接時,也建立與客戶端的連接,即所謂的雙向連接。所以,在Packet2中,服務器將ACK和SYN打包發出。揮手,即關閉連接,往往只是表明揮手方不再發送數據(無數據可發),而接收通道依然有效(依然可以接受數據)。當對方也揮手時,則表明對方也無數據可發了,此時雙向連接真正關閉。

 

參考:

《瀏覽器/網頁工作原理》《What really happens when you navigate to a URL》

《HTTP通信過程分析》

《究竟什么是HTTP連接》

《一次完整的HTTP通信步驟》

《SOCKET與TCP/IP與HTTP的關系》

《TCP連接、Http連接與Socket連接》

《TCP傳輸協議抓包經驗》
————————————————
版權聲明:本文為CSDN博主「弦苦」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/phunxm/java/article/details/5836034


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM