更好閱讀體驗:《理解 TCP 和 UDP》— By Gitbook
TCP 是面向位元組流的,但傳送的資料單元卻是報文段。
什麼是報文?
例如一個 100kb 的 HTML 文件需要傳送到另外一臺計算機,並不會整個文件直接傳送過去,可能會切割成幾個部分,比如四個分別為 25kb 的資料段。
而每個資料段再加上一個 TCP 首部,就組成了 TCP 報文。
一共四個 TCP 報文,傳送到另外一個端。
另外一端收到資料包,然後再剔除 TCP 首部,組裝起來。
等到四個資料包都收到了,就能還原出來一個完整的 HTML 文件了。
在 OSI 的七層協議中,第二層(資料鏈路層)的資料叫「Frame」,第三層(網路層)上的資料叫「Packet」,第四層(傳輸層)的資料叫「Segment」。
TCP 報文 (Segment),包括首部和資料部分。
而 TCP 的全部功能都體現在它首部中各欄位的作用,只有弄清 TCP 首部各欄位的作用才能掌握 TCP 的工作原理。
TCP 報文段首部的前20個位元組是固定的,後面有 4N 位元組是根據需要而增加的。
下圖是把 TCP 報文中的首部放大來看。
TCP 的首部包括以下內容:
- 源埠 source port
- 目的埠 destination port
- 序號 sequence number
- 確認號 acknowledgment number
- 資料偏移 offset
- 保留 reserved
- 標誌位 tcp flags
- 視窗大小 window size
- 檢驗和 checksum
- 緊急指標 urgent pointer
- 選項 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 就把緊急資料插入到本報文段資料的最前面,而在緊急資料後面的資料仍是普通資料。
因此,緊急指標指出了緊急資料的末尾在報文段中的位置。