序列號 (Sequence Number, SEQ) 是 TCP 表頭的欄位之一,
欄位大小為 32 bits,因此其 數值範圍 為 0 ~ 232 – 1,
是 TCP 設計的根本概念,幾乎所有功能都依賴此欄位完成。
目錄
可靠性 (Reliability)
TCP 流量控制 (Flow Control) 中提過,
TCP 每次 發送 與 接收 單位為: TCP 區段 (TCP Segment),
每個區段的大小不盡相同,有可能 數百~數萬 個位元組。
就像 最大區段長度 (Maximum Segment Size, MSS),
指的是 所能接收 『資料』的最大長度,而非區段!
TCP 會為每條連線發送的 資料位元組 (octet of data) 分配 序列號,
而 序列號 (Sequence Number, SEQ) 欄位,
放的是該區段 資料位元組 的 第一個序列號 (除非無攜帶資料)!
(真心覺得這些命名很瞎 🙄)
TCP/IP 的網路層 — — IP 協定,不保證資料會照發送順序抵達 接收端,
接收端 可利用表頭中的 序列號 (Sequence Number, SEQ) 欄位 進行排序、消除重複 (eliminate duplicates),
以保證資料接收的正確順序,並以 位元組串流 (byte-stream) 的方式,傳遞給應用層。
TCP 使用 確認號 (Acknowledgment Number) 欄位,
指出下一個期望接收的 序列號 (Sequence Number, SEQ)。
(表示 編號小於此值的位元組,皆已正確接收)
again:
序列號 (Sequence Number, SEQ),並不是 區段的 id 或 編號 !
它不代表一個唯一的 區段,
且不同於資料庫的主鍵,其值有可能重複。
無攜帶資料
有些區段並不會攜帶資料,自然不存在 資料位元組。
如:
- 建立、結束連線
- 無攜帶資料之 確認區段
- …
儘管其值無效,該 區段 仍需使用一個 序列號 (Sequence Number, SEQ)。
初始序列號 (Initial Sequence Number, ISN)
為了避免與先前連線的區段混淆,
當次連線建立時,序列號 並非從 0 開始,
兩端會使用 ISN 產生器,產生各自的 初始序列號 (Initial Sequence Number, ISN),
通常兩者並不相等,且如本篇開頭所述,數值範圍 為 0 ~ 232 – 1。
連線建立時,透過 控制位元 (Control Bits) 中的 SYN,
讓兩端的 TCP 必須進行 ISN 的交換 (同步),
SYN 全名 同步序列號 (Synchronize sequence numbers),
使用 SYN,代表目前區段的 序列號 為 初始序列號,
而非 資料位元組 的第一個序列號。
這就是 TCP 連線的建立方式,
且 2 和 3,可以組合為單一訊息,
即大名鼎鼎的 — — TCP 三向交握 (Three Way Handshake)。
Ex:
而 第三個區段 (Client — — > Server),
其 SEQ 為 第一個區段的值 + 1 (ISN + 1)。
相對序列號 (Relative Sequence Number)
如果你有用 Wireshark 之類的封包分析軟體,
可能會以為我爪你: 「ISN 就是 0 啊,根本不是亂數 🙄」。
那不是真的 SEQ,而是相對 SEQ!
真正的值可能很大很難看,
為了方便觀察,大部分工具都會提供相對 SEQ。
(將 ISN 做為基底值)
要取消可以按右鍵設定:
接著,就可以看到很鏘的數:
無攜帶資料之 確認區段
大部分 TCP 實作,對 無攜帶資料 之 確認 (ACK) 區段,
視為 序列號無效,並且 不消耗任何序列號。
也就是:
序列號 (SEQ) 將重複使用,直到區段攜帶資料。
範例
承上述範例,第三個區段 (Client — — > Server) 的 SEQ 為 101 (此時連線建立完成),
第四個區段,送出 攜帶資料的 區段 (Client — — > Server),
SEQ 將同樣為 101,而非 102 (101 + 1)。
(因為第三個區段 是 無攜帶資料之 確認區段,序列號將重複使用)
別忘記了,區段長度 (Segment Len) 是個腦殘的命名,
指的是 資料長度,而非區段。
Segment Len: 999 代表「含序列號 101 的資料,共有 999 個資料位元組」,
(101、102、103、…、…、1098、1099)
假設成功送達 Server,且區段沒有毀損,
第五個區段 確認號 (Acknowledgment Number) 將設為 1100,
(表示編號小於 1100 的位元組,皆已正確接收)
第六 與 第七個區段 (Client < — — Server),Server 送出攜帶 1440 (位元組) 資料的 區段,
由於尚未收到 Client 回覆,「期望收到的 序列號」 = 確認號 (ACK Number),與第五個區段 一樣為 1100。
第八個區段 (Client — — > Server),
一樣是 無攜帶資料之 確認區段 區段。
因此,如果有 第九個區段 (Client < — — Server) (懶得畫了😂),
Server 之 確認號 (ACK Number) 將一樣為 1100。
第十個區段 (Client — — > Server),
Client 之 序列號,也將維持 1100 不變,直到其攜帶資料。
無攜帶資料之 確認區段,
其 序列號 (SEQ) 將 重複使用,直到區段攜帶資料 或 拆除連線。
在《TCP 序列號 (Sequence Number, SEQ)》中有 6 則留言
文章寫得太好了,非常讚賞。但我有些問題請教:
step 6 的 1440 從何來?
以及是否 handshake 的頭三個step 才加1?
文章寫得太好了,非常讚賞。但我有些問題請教:
step 6 的 1440 從何來?
以及是否 handshake 的頭三個step 才加1?
那個是資料的長度
請問為什麼 第六區段 client 會沒有回覆,需要再送第七區段?
是指例外情況,比如資料遺失或等待client ACK time out?
還是說 傳接資料不一定是一端發了另一端就要馬上送? 一端可以一次發送好幾筆TCP Segments,彼端只需要一次ACK?
非常謝謝你,你就是我的期中救星!