TCP三次握四次揮手里seq和ack號的【正確】理解


1 理論知識

先上一張圖,TCP/IP詳解第18章的這張圖描述了一個正常的三次握手和四次揮手的狀態遷移,以及seq、ack序號的變化。

基本狀態看圖就能了解,本文主要圍繞序號的變化進行講解。

clipboard

1)seq序號

seq的初始值在不同系統實現不一樣,一般為隨時間增長的值。當seq超過4字節存儲空間后從0開始。

在某個方向上傳輸N個字節的數據,序列號就+N,因此seq用於確認在某個方向上傳輸的字節數。

如果傳輸的數據字節為0,即只有首部,那序列號還增加嗎?當syn 或 fin被置1,雖然報文里長度為0,計算ACK時我們可以認為其長度為1。其他情況(如只有ack)不增加。

2)ack序列號

只有ack標志置1才有效。在TCP交互的整個周期,除了syn包外其他所有包ack都被置1。

ack序列號是上個報文的序列號+已經成功收到數據長度,比如上次成功接收了seq為1,長度為1000的數據,發送的ack序號為1001,表示我seq1000以前的數據我已經成功接收了,我對序列號1001開始的數據感興趣。

2 實例

clipboard

這是一次http交互的一個例子。①~③為三次握手,④~⑥為數據傳送階段,⑦~⑨為四次揮手過程(這里實際只有三個包,因為⑧結合了fin和ack兩個步驟)。

我們看第一個包的seq和ack都是0,這是wireshark為了方便閱讀將序號重0開始計算(沒有改變實際值),我們看到有字段里有兩個帶RAW的字段,它們才是序號真實的值。

注:

1)在下面的解析中,我們不會使用raw的值,但為了說明不是從0開始,我們取整數10000和20000作為兩端seq的初始值。

2)192.168.31.21記為A,211.158.235.30記為B。

2.1 三次握手過程

序號變化(假設從10000和20000作為初始值):

image

首先A向B發一個SYN包,告訴B請求建立連接。seq為初始化的隨機值(如何初始化和系統具體實現有關),這里假設為10000,此時ACK序號為0。

B收到后會發一個對SYN包的確認包(SYN+ACK)回去,表示對第一個SYN包的確認,並繼續握手操作。

此時B也以一個隨機值來初始化seq(與A無關),這里假設為20000。B的ACK是A的seq加1,即10000+1=10001。表示你的請求我已收到,我這方的序號就從20000開始,由於你的syn包消耗了1字節,我期望下一個收到的序列號從10001開始。

A收到SYN+ACK 包后回一個確認包(ACK)通知B連接已建立。

它的seq是上個請求(①)的seq加1,即10000+1=10001,當然也等於上一個包(②)的ACK,ACK是B的seq加1,即20000+1=20001,用於確認收到②(syn被置位,所以也消耗了1字節)。

至此,三次握手完成,一個TCP連接建立完成。

2.2 數據傳輸階段

image

④ A發起Get請求,由於上一個③的len=0,且沒有syn或fin標志,因此沒有消耗seq的值,seq不變還是10001。ACK序號確認的還是上一個收到的②(這段期間也沒有收到新的包)。

⑤ B對收到的④發出回應,告訴A我已經收到。由於上一個請求②消耗了1字節,這里seq為20001。ACK為④的seq+len=10001+183=10184。

⑥ B發送200ok,由於⑤長度為0沒有消耗seq,這里seq仍然為20001,ACK序號確認的還是上一個收到的④。

2.3 四次揮手

計算過程基本相同,幾個注意點是:

1)A對⑥的確認合並到第一個揮手包里了。

2)⑧將FIN和ACK原本的兩次揮手合並。

image

⑦ 確認⑥,並發出揮手。

⑧ 確認⑦,並發出揮手。⑦長度0,但是有FIN標志,消耗1字節,ACK=10184+1=10185。

⑨ 確認⑧,雖然⑧長度為0,但是有FIN標志,消耗1字節,ACK=20155+1=20156。至此揮手完成,TCP整個生命周期結束。


免責聲明!

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



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