TCP-IP詳解:TCP的連接與終止

參考書籍:TCP-IP詳解


基本概念

ISN: 初始的序列號,Sequeue Number,TCP 協議棧爲每一個封包都會分配一個sequence number,主要用來保證順序的問題

MSS:最大報文長度,發送的報文不要超過這個值,一般情況下MTU-IP Header - TCP Header

ACK:確認序號,表明下一個需要接收的包的Sequeue number,可以通過這個來盡最大可能保證不丟包

Window Size: 滑動窗口,解決流量控制


三次握手(Three handshake)

    1.請求端先發送一個SYN包(圖中的103包),告訴連接服務器端口及ISN,如下圖Seq = 0,MSS = 1460(MTU = 1500) Window Size = 65535

    2.服務器會對SYN包做一個迴應,ACK = 1(103包的Seq + 1), 即期望獲得Seq = 1的包,然後告知Windwos和MSS

    3.客戶端收到[SYN ACK]包,然後將Seq = 1發送一個ACK包,對服務器來的ACK進行確認

這樣就完成了三次握手,成功建立了一個連接,接下來就可以正常發送數據了!

說明:在TCPdump中看到的三次握手的seq number總是爲0,但是實際上真實的協議棧不是這樣的,ISN是一個隨時間變化的值,不能是Hard Code,在這裏如此實際上是Tcpdump做了優化,顯示了一個相對的值,可以通過右鍵,Protocal option中的Ralative SeqNum取消掉即可。

下圖是三次握手的示意圖,X,Y就是一開始的ISN了


對於Seq number是如何變化的,可以看下整個流的流量圖,這裏可以看到一點:單獨的ACK不會消耗Seq number,Seq Number的增加是和傳輸的字節數相關的,可以看到三次握手之後,客戶端開始發數據,這個時候Seq = 1, 發了161長度的數據包,對方回覆了一個ACK = 162,也就說162前面的我已經都收到,請發162及之後的數據,接着 服務器又回覆了一個1340長度的數據包,客戶端給予一個ACK = 1341的確認!


四次揮手

        終止一個連接要經過4次揮手,其實這個主要是由於TCP的半關閉造成的,TCP屬於全雙工的通訊,既能發又能收,當然可以關閉一部分,比如說讓這個接口只能收不能發,這就是半關閉了,每一方都需要關閉,才能完成真正的關閉!

        1)一般情況下客戶端首先關閉,即發起一個FIN包,首先執行關閉的一端叫主動關閉,另一方成爲被動關閉

        2)服務器收到客戶端的FIN包之後,會發會一個ACK包,確認序號爲收到的需要加一,說明FIN包和SYN包一樣都佔用一個序號

3)客戶端收到ACK包之後,說明客戶端已經半關閉了,這個時候只能接收數據包,但是不能發送數據包

4)如果服務器也完成了發送數據需要關閉鏈接,TCP端就會發送一個FIN包給客戶端

5)  客戶端收到FIN包之後,就回復一個ACK表示收到,連接關閉

詳細的過程可以參考下圖:


連接建立超時

很多狀況下,客戶端無法連接到服務器上,基本都是發送SYN包,服務器端由於一些故障,沒有回覆SYN ACK,可以看一個實驗的tcpdump結果,重新發送SYN包的事件間隔分別是 1s 2s 4s 8s 16s 32s,這個規律很好尋找,時間按照2^n次方的規律遞增



TCP的半關閉

TCP提供了連接的一端在結束它的發送後還能接收來自另外一端數據的能力。這就是所謂的半關閉,不過這種Case在應用程序中比較少的使用。

如果應用程序不調用close而調用shutdown,且第二個參數值爲1,則這個socket的API支持半關閉!其實對於全雙工的TCP協議來講,只是關閉了發送數據的功能,但是還可以接收數據! 

下圖顯示了一個典型的列子,讓左邊的客戶端開始半關閉,發送FIN包,然後右端收到FIN包之後認爲對端已經發送完數據了,回覆ACK,這條路就徹底被切斷了,目前的狀況客戶端只能收不能發了,所以右端的服務器仍然可以write數據給客戶端,到服務器真正把所有數據發完的時候,會發FIN包來關閉連接,客戶端收到FIN,回覆ACK,連接徹底關閉。 不過再次重申 這種場景比較少用哦,瞭解即可。






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