TCP頭部分析與確認號的理解

一、TCP的特色:html

基於字節流
面向鏈接
可靠傳輸
緩衝傳輸
全雙工
流量控制緩存

 

二、頭部格式和說明服務器

圖源百度。以下圖示,就是TCP包的頭部結構。能夠看到這個頭部最少有4x5=20個字節。網絡

另外還須要理解TCP協議是承載在IP協議中的。關於IP協議能夠參考:http://www.cnblogs.com/xcywt/p/8067521.htmltcp

源端口號和目的端口號:再加上Ip首部的源IP地址和目的IP地址能夠惟一肯定一個TCP鏈接
數據序號:表示在這個報文段中的第一個數據字節序號
確認序號:僅當ACK標誌爲1時有效。確認號表示指望收到的下一個字節的序號(這個下面再詳細分析)
偏移:就是頭部長度,有4位,跟IP頭部同樣,以4字節爲單位。最大是60個字節
保留位:6位,必須爲0
6個標誌位:
URG-緊急指針有效
ACK-確認序號有效
PSH-接收方應儘快將這個報文交給應用層
RST-鏈接重置
SYN-同步序號用來發起一個鏈接
FIN-終止一個鏈接ui

窗口字段:16位,表明的是窗口的字節容量,也就是TCP的標準窗口最大爲2^16 - 1 = 65535個字節(這個下面再詳細分析)spa

校驗和:源機器基於數據內容計算一個數值,收信息機要與源機器數值 結果徹底同樣,從而證實數據的有效性。檢驗和覆蓋了整個的TCP報文段:這是一個強制性的字段,必定是由發送端計算和存儲,並由接收端進行驗證的。.net

緊急指針:是一個正偏移量,與序號字段中的值相加表示緊急數據最後一個字節的序號。TCP的緊急方式是發送端向另外一端發送緊急數據的一種方式
選項與填充(必須爲4字節整數倍,不夠補0):
最多見的可選字段的最長報文大小MSS(Maximum Segment Size),每一個鏈接方一般都在一個報文段中指明這個選項。它指明本端所能接收的最大長度的報文段。
該選項若是不設置,默認爲536(20+20+536=576字節的IP數據報)unix

 

三、TCP如何保證可靠性指針

1)應用數據被分割成TCP認爲最合適發送的數據塊。稱爲段(Segment)傳遞給IP層
2)當TCP發出一個段後,它會啓動一個定時器,等待目的端確認收到這個報文段。若沒有及時收到確認,將從新發送這個報文段
3)當TCP收到發自TCP鏈接另外一端的數據,它將發送一個確認。這個確認不是當即發送的,一般將推遲幾分之一秒。
4)TCP將保持它首部和數據的校驗和,這是一個端到端的校驗和,目的是檢測數據在傳輸過程當中的任何變化。若是收到段的校驗和有差錯,TCP將丟棄這個報文也不進行確認(對方就會重複發送了)。
5)TCP承載與IP數據報來傳輸,而IP數據報可能會失序,因此TCP的報文段到達時也可能會失序。可是TCP收到數據後會從新排序到正確的順序(經過序號)。
6)IP數據報會發生重複,TCP的接收端必須丟棄重複是數據
7)TCP還能提供流量控制,TCP鏈接的每一方都有必定大小的緩衝空間

 

 四、滑動窗口協議(也就是對包頭中窗口字段的理解)

參考1:https://www.cnblogs.com/ulihj/archive/2011/01/06/1927613.html

參考2:http://blog.chinaunix.net/uid-26275986-id-4109679.html

先上兩個概念:
通告接收窗口(rwnd):預防應用程序發送的數據超過對方的緩衝區,接收方使用的流量控制。
擁塞窗口(cwnd):預防應用程序發送的數據超過了網絡所能承載的能力。發送方使用的流量控制。
發送窗口:就是指上面二者的較小值

因爲TCP的全雙工的,因此其實TCP雙方各自都維護一個發送窗口和接收窗口。

假設是主機A發送給主機B
A和B都會維護一個數據幀的序列,這個序列稱爲窗口。發送方的窗口大小由接收方肯定。目的在於控制發送速度。以避免接收方的緩存不夠大而致使溢出,同時流量控制也能夠避免網絡擁塞。
這裏實際上是指A的發送窗口。


假設A發送了不少段給B,序號是1-10.這些段會處於種狀態:
1)已發送,已確認
2)已發送,未確認
3)等待發送
4)不容許發送

正常狀況下,每一個段都會由4狀態->3狀態->2狀態->1狀態。而窗口就是指處於狀態2和狀態3的總數。
由2狀態->1狀態的時候,窗口就會日後滑動一下,表示最近那個4狀態的段能夠變成3狀態了。
若是接收方一直不確認,那麼處於4狀態的段將永遠不會被髮送。
當窗口滿了的時候,4狀態的段將不會變成3狀態。從而達到了控制發送速度的做用。

就像上圖同樣,123處於1狀態,456處於2狀態,789處於3狀態,10之後的處於4狀態。而窗口就是指哪一個框起來的。這裏爲6。

隨着發送段被逐一的確認,這個窗口會往右滑動。

就像一個水池,整體積V,進水速度是s1,出水速度s2。當水池滿了就不能再注入了,強行注入會溢出丟失。窗口就是那個水池。

滑動窗口實現面向流的可靠性:

1)最基本的傳輸可靠性來源於確認重傳機制
2)滑動窗口的可靠性也是創建在確認重傳機制上的
3)發送窗口只有收到目的端口對本段發送窗口內字節的ACK確認,纔會移動發送串口的左邊界。
4)接收窗口只有在前面全部的段都確認的狀況下才會移動左邊界。當在前面還有段未收到確認,可是收到了後面段的狀況下,窗口不會移動,也不對後續段進行確認。以此確保發送端會對這個數據重傳。

 

五、關於包頭中確認號ack的理解

 確認序號:僅當ACK標誌爲1時有效。確認號表示指望收到的下一個字節的序號

這裏是拿三次握手以後,開始傳輸數據了進行分析。

服務器向客戶端發送一個數據包後,客戶端收到了這個數據包,會向服務器發送一個確認數據包。

傳輸數據的簡要過程以下:

1)發送數據:服務器向客戶端發送一個帶有數據的數據包。該數據包中的序列號和確認號與創建鏈接第三步的數據包找那個的序列號和確認號相同。

2)確認收到:客戶端收到該數據包,向服務器發送一個確認數據包。該數據包中,序列號是爲上一個數據包中的確認號值。

而確認號爲服務器發送的上一個數據包中的序列號+該數據包中所帶數據的大小。

回覆確認收到的ack = 收到了序列號 + 數據的大小(同時也表示下一次指望收到的序號)

這裏咱們直接拿Wireshark抓包進行分析:

實例1:客戶端給服務器發送了」xcychongyong」 共13個字節。

先看,服務器收到的,也就是客戶端發送的:seq是10,數據長度是13.

再來看服務器發送給客戶端的確認包:根據上面的說明。ack應該是10 + 13 = 23

 

實例2:

以下圖,208(就是192.168.0.208)一共向182(就是192.168.0.182)發送了6組數據。

過濾條件:tcp and (ip.src==192.168.0.182 or ip.dst==192.168.0.182)

對於182來講:

第一次迴應時ack是4,結果208下一次發送的序號就是4。

第二次迴應時ack是10,結果208下一次發送的序號就是10。

第三次迴應時ack是19,結果208下一次發送的序號就是19。

以此類推…

 

再來分析一個互相發送的:

如圖,一共發送了5次:

第一次182發給208,發的長度是7,seq是1.因此208回覆的ack是8。也至關於告訴182:「182,你下次發的時候,序號就從8開始」。看第2個紅框,seq就是8.

第二次208發給182,發的長度是11,seq是1,因此182回覆的ack是12。也至關於告訴208:「208,你下次發的時候,序號就從12開始」。看第2個綠框,seq就是12.

同理,

182再發送一次給208,seq應該是17  

208再發送一次給182,seq應該是33

 

ack表示指望下次接收到的序號。

那麼ack是如何算出來的呢,就是經過收到的序號,和數據長度相加得來。

假設A收到B過來的數據(seq = 5,len = 15)。len表示數據長度。

那麼A就會回覆B,「剛纔的數據我已經收到了,你接下來就發序號爲20的包給我吧」。這樣就保證了數據不會亂序。

 綜上,確認號就是下一次將要收到包的序號。同時也等於發送方的序號+數據長度(確認號在ACK標誌位有效時纔有用。)

相關文章
相關標籤/搜索