TCP 三向交握 (Three-way Handshake)

傳輸控制協定 (Transmission Control Protocol, TCP) 不像 UDP,
TCP 是一種 連接導向 (connection-oriented) 的通訊協定,
三向交握 (Three-way Handshake), 是其建立虛擬連線 (virtual connection) 的方式。
 
又稱為 三向式握手、三路交握 …,其實就是 三次訊息的交換
 


 

三向交握 (Three-way Handshake)

三向交握 (Three-way Handshake) 常簡略表示為:
 
 三向交握
 
 
其中 SYNACK 是 TCP 封包中的 控制位元 (Control Bits)
過程中省略了其他封包內容,例如:
三向交握 範例
(數值只為範例,不代表實際情形,為避免爭議,使用的是官方的範例數值)
 
 

範例說明:先寄三個編號包裹

想像 Alice 與 Bob 準備互寄重要的東西,但他們不會一開始就把東西塞進管道。因為他們都怕:

  • 「我明明寄了,你卻完全沒收到。」(封包可能遺失;某個方向的路徑或防火牆也可能不通。)
  • 「你手上的這包,是剛寄的,還是上次卡在路上、現在才飄來的舊包裹?」(封包可能延遲、重複,或屬於舊連線。)
  • 「我收到了你的回覆,但你真的知道我收到了嗎?」(只確認單向可達還不夠,雙方都要建立相同的連線狀態。)

 
所以他們先寄三個空的編號包裹。包裹外面有寄件編號(TCP header 的 sequence number);裡面可裝東西(payload),也可以是空的。
 

  1. Alice 寄出藍色包裹 100,內容通常為空:
    「我這邊準備從 100 開始寄。」
    SYN, SEQ=100
  2. Bob 收到後,寄回黃色包裹 300
    「100 收到;你下次請寄 101。我這邊從 300 開始。」
    SYN+ACK, SEQ=300, ACK=101
  3. Alice 收到後,寄出藍色包裹:
    「300 收到;你下次請寄 301。」
    ACK, SEQ=101, ACK=301

 
完成第三步時,Alice 已知道 Bob 能收;Bob 收到第三步後,也知道 Alice 收到了自己的回覆。兩邊的 TCP 狀態才都進入 ESTABLISHED
 

教學圖通常把前三個包裹畫成空的,方便看清 SYN、ACK 與編號。這不是協定限制:SYN 可以攜帶資料,而第三個 ACK 也可以順便帶第一份資料。

 


 

TCP 表頭格式 (TCP Header Format)

TCP-Header-Format
 
有了基本概念後,再看 TCP 的封包格式,便能快速上手!
控制位元 (Control Bits) 不過是 0 與 1 的切換 😀。
 
 

SYN (Synchronize sequence numbers)

  • 用於連線建立期間同步序列號;第一個 SYN 是請求,SYN+ACK 也同樣帶有 SYN。
  • SYN 本身會消耗一個序列號;它通常不帶資料,但協定允許攜帶。

 
 

ACK (Acknowledgment field significant)

  • 如果有設置,使 確認號欄位 有效。

 
 

Sequence Number (序列號)

相當於上例的 漫畫 “集數”:

  • 如果 SYN 控制符 未設置,則為此區段第一個資料位元組 (octet) 的序列號。
  • 如果 SYN 控制符 已設置,則此為初始序列號 (initial sequence number , ISN),
    第一個資料位元組 (octet) 的序列號為 ISN + 1。
  • 每個藉由 TCP 連線傳送的資料的位元組,都會有一個序列號。

 
更多介紹,詳見 TCP 序列號 (Sequence Number, SEQ)
 
 

Acknowledgment Number (確認號)

  • 當確認連線後(已設置 ACK),這邊存放想要接收的 Seq 順序號。
  • 一旦連線建立,則每次都需送出。

 
更多介紹,詳見 TCP 錯誤控制 (Error Control)
 


 

資料區段 (Segment)

值得一提的是:
許多人誤解了三向式握手的 確認號 (ACK Number)
以為就是拿對方的 序列號 (Sequence Number) 再加 1 。
而忽略了 TCP Segment (資料區段)資料長度 (Len)
 
 
TCP Segment(資料區段) 是由 TCP header、可選 options,以及零或多個資料位元組組成,並由 IP datagram 承載。為了方便溝通,日常常說「TCP 封包」;但討論 TCP 語意時,使用 segment 更精確。
 
在最簡化的三向交握中,三個 segment 的 payload length 都是 0;但 SYN 仍消耗一個序列號,所以才會看到 ACK=SEQ+1
 
更完整的規則是:

ACK Number = SEG.SEQ
           + payload length
           + (SYN ? 1 : 0)
           + (FIN ? 1 : 0)

 
因此,若第三步 ACK 順便攜帶 87 bytes 的資料,下一個 ACK 會在 Alice 的 SEQ=101 基礎上期待 188;不是永遠只加 1。
 
詳見 RFC 9293
 
三向交握範例
 
 

作者: 鄭中勝
喜愛音樂,但不知為何總在打程式 ? 期許能重新審視、整理自身所學,幫助有需要的人。

在〈TCP 三向交握 (Three-way Handshake)〉中有 13 則留言

  1. 自動引用通知: TCP – 我好想要中樂透
  2. 自動引用通知: TCP三次握手 | 大专栏
  3. 剛開始把SYN當成SEQ的號碼(其他網站常寫SYN=K,ACK=J+1),所以一開始才會看不懂,要把SYN當成0/1控制碼來看。

    感謝作者的詳細解說。

發表迴響