理解 TCP(二):報文結構

JerryC發表於2017-03-02

更好閱讀體驗:《理解 TCP 和 UDP》— By Gitbook

TCP 是面向位元組流的,但傳送的資料單元卻是報文段。

什麼是報文?
例如一個 100kb 的 HTML 文件需要傳送到另外一臺計算機,並不會整個文件直接傳送過去,可能會切割成幾個部分,比如四個分別為 25kb 的資料段。
而每個資料段再加上一個 TCP 首部,就組成了 TCP 報文。
一共四個 TCP 報文,傳送到另外一個端。
另外一端收到資料包,然後再剔除 TCP 首部,組裝起來。
等到四個資料包都收到了,就能還原出來一個完整的 HTML 文件了。

在 OSI 的七層協議中,第二層(資料鏈路層)的資料叫「Frame」,第三層(網路層)上的資料叫「Packet」,第四層(傳輸層)的資料叫「Segment」。

TCP 報文 (Segment),包括首部和資料部分。

理解 TCP(二):報文結構
報文結構.png

而 TCP 的全部功能都體現在它首部中各欄位的作用,只有弄清 TCP 首部各欄位的作用才能掌握 TCP 的工作原理。
TCP 報文段首部的前20個位元組是固定的,後面有 4N 位元組是根據需要而增加的。
下圖是把 TCP 報文中的首部放大來看。

理解 TCP(二):報文結構
報文首部結構.png

TCP 的首部包括以下內容:

  1. 源埠 source port
  2. 目的埠 destination port
  3. 序號 sequence number
  4. 確認號 acknowledgment number
  5. 資料偏移 offset
  6. 保留 reserved
  7. 標誌位 tcp flags
  8. 視窗大小 window size
  9. 檢驗和 checksum
  10. 緊急指標 urgent pointer
  11. 選項 tcp options

下面展開來描述個欄位的意義和作用。

TCP 首部各欄位的意義和作用

源埠和目的埠 Port

各佔 2 個 位元組,共 4 個位元組。
用來告知主機該報文段是來自哪裡以及傳送給哪個應用程式(應用程式繫結了埠)的。
進行 TCP 通訊時,客戶端通常使用系統自動選擇的臨時埠號,而伺服器則使用知名服務埠號。

序號 Sequence Number

佔 4 個位元組。
TCP 是面向位元組流的,在一個 TCP 連線中傳輸的位元組流中的每個位元組都按照順序編號。
例如 100 kb 的 HTML 文件資料,一共 102400 (100 * 1024) 個位元組,那麼每一個位元組就都有了編號,整個文件的編號的範圍是 0 ~ 102399。

序號欄位值指的是本報文段所傳送的資料的第一個位元組的序號。
那麼 100 的 HTML 文件分割成四個等分之後,
第一個 TCP 報文段包含的是第一個 25kb 的資料,0 ~ 25599 位元組, 該報文的序號的值就是:0
第二個 TCP 報文段包含的是第二個 25kb 的資料,25600 ~ 51199 位元組,該報文的序號的值就是:25600
......

根據 8 位 = 1 位元組,那麼 4 個位元組可以表示的數值範圍:[0, 2^32],一共 2^32 (4294967296) 個序號。
序號增加到最大值的時候,下一個序號又回到了 0.
也就是說 TCP 協議可對 4GB 的資料進行編號,在一般情況下可保證當序號重複使用時,舊序號的資料早已經通過網路到達終點或者丟失了。

確認號 Acknowledgemt Number

佔 4 個位元組。
表示期望收到對方下一個報文段的序號值
TCP 的可靠性,是建立在「每一個資料包文都需要確認收到」的基礎之上的。
就是說,通訊的任何一方在收到對方的一個報文之後,都要傳送一個相對應的「確認報文」,來表達確認收到。
那麼,確認報文,就會包含確認號
例如,通訊的一方收到了第一個 25kb 的報文,該報文的 序號值=0,那麼就需要回復一個確認報文,其中的確認號 = 25600.

資料偏移 Offset

佔 0.5 個位元組 (4 位)。
這個欄位實際上是指出了 TCP 報文段的首部長度 ,它指出了 TCP報文段的資料起始處 距離 TCP報文的起始處 有多遠。(注意 資料起始處 和 報文起始處 的意思)

一個資料偏移量 = 4 byte,由於 4 位二進位制數能表示的最大十進位制數字是 15,因此資料偏移的最大值是 60 byte,這也側面限制了 TCP 首部的最大長度。

保留 Reserved

佔 0.75 個位元組 (6 位)。
保留為今後使用,但目前應置為 0。

標誌位 TCP Flags

標誌位,一共有 6 個,分別佔 1 位,共 6 位 。
每一位的值只有 0 和 1,分別表達不同意思。

緊急 URG (Urgent)

當 URG = 1 的時候,表示緊急指標(Urgent Pointer)有效。
它告訴系統此報文段中有緊急資料,應儘快傳送,而不要按原來的排隊順序來傳送。
URG 要與首部中的 緊急指標 欄位配合使用。

確認 ACK (Acknowlegemt)

當 ACK = 1 的時候,確認號(Acknowledgemt Number)有效。
一般稱攜帶 ACK 標誌的 TCP 報文段為「確認報文段」。
TCP 規定,在連線建立後所有傳送的報文段都必須把 ACK 設定為 1。

推送 PSH (Push)

當 PSH = 1 的時候,表示該報文段高優先順序,接收方 TCP 應該儘快推送給接收應用程式,而不用等到整個 TCP 快取都填滿了後再交付。

復位 RST (Reset)

當 RST = 1 的時候,表示 TCP 連線中出現嚴重錯誤,需要釋放並重新建立連線。
一般稱攜帶 RST 標誌的 TCP 報文段為「復位報文段」。

同步 SYN (SYNchronization)

當 SYN = 1 的時候,表明這是一個請求連線報文段。
一般稱攜帶 SYN 標誌的 TCP 報文段為「同步報文段」。
在 TCP 三次握手中的第一個報文就是同步報文段,在連線建立時用來同步序號。
對方若同意建立連線,則應在響應的報文段中使 SYN = 1 和 ACK = 1。

終止 FIN (Finis)

當 FIN = 1 時,表示此報文段的傳送方的資料已經傳送完畢,並要求釋放 TCP 連線。
一般稱攜帶 FIN 的報文段為「結束報文段」。
在 TCP 四次揮手釋放連線的時候,就會用到該標誌。

視窗大小 Window Size

佔 2 位元組。
該欄位明確指出了現在允許對方傳送的資料量,它告訴對方本端的 TCP 接收緩衝區還能容納多少位元組的資料,這樣對方就可以控制傳送資料的速度。
視窗大小的值是指,從本報文段首部中的確認號算起,接收方目前允許對方傳送的資料量。
例如,假如確認號是 701 ,視窗欄位是 1000。這就表明,從 701 號算起,傳送此報文段的一方還有接收 1000 (位元組序號是 701 ~ 1700) 個位元組的資料的接收快取空間。

校驗和 TCP Checksum

佔 2 個位元組。
由傳送端填充,接收端對 TCP 報文段執行 CRC 演算法,以檢驗 TCP 報文段在傳輸過程中是否損壞,如果損壞這丟棄。
檢驗範圍包括首部和資料兩部分,這也是 TCP 可靠傳輸的一個重要保障。

緊急指標 Urgent Pointer

佔 2 個位元組。
僅在 URG = 1 時才有意義,它指出本報文段中的緊急資料的位元組數。
當 URG = 1 時,傳送方 TCP 就把緊急資料插入到本報文段資料的最前面,而在緊急資料後面的資料仍是普通資料。
因此,緊急指標指出了緊急資料的末尾在報文段中的位置。

參考

《後臺開發 核心技術與應用實踐》
《計算機網路》

相關文章