TCP 三向交握 (Three-way Handshake) 一文中,
說明了 TCP 建立連線的方式,並提及了 Segment (區段) 的觀念。
TCP 使用 錯誤控制 (Error Control) 機制,
確保了傳輸的可靠性 (reliable),
其中最常見的是: 檢驗和 (checksum)、確認 (acknowledgement)、逾時 (time-out)。
本篇將說明 TCP Checksum 的運作方式。
檢驗和 (Checksum)
檢驗和 (Checksum),提供 傳送方 與 接收方 一種計算方式,
用來檢查 區段 (segment) 是否受損。
發送方:
欲發送 TCP 區段前,利用此計算方式 算出 Checksum 值,
並置於 Checksum 欄位。
接收方:
將收到的區段,透過相同的計算方式算出 Checksum 值。
並與收到 TCP 區段的 Checksum 欄位值做比較,
若兩者不相等,目的端會丟棄此區段,並視同區段遺失。
虛擬表頭 (Pseudo-Header) — IPv4
在說明 計算方式 之前,得先說說 虛擬表頭 (Pseudo-Header)!
如上圖 (TCP 表頭格式),TCP 本身沒有關於位址的訊息,
這可能造成 區段 (segment) 被 錯誤的路由 (misrouted)。
因此,需提供足夠的資訊,讓 checksum 可檢測路由錯誤,
這些資訊就是 — 虛擬表頭 (Pseudo-Header) 啦!
總共有 12 個位元組 (octet) 也就是 96 (12*8) 位元。
之所以稱 虛擬 (Pseudo),
是因為這僅供 checksum 計算使用,並不實際傳送。
(位址欄位來自 IP 表頭)
- 來源位址 (Source Address):
32 位元的來源 IPv4 位址 - 目的位址 (Destination Address):
32 位元的目的 IPv4 位址 - Zero:
顧名思義 (00000000) - PTCL:
通訊協定 (protocol) 的縮寫,
用來指示使用的 通訊協定 的代號,
TCP 為 6,UDP 為 17。 - TCP Length:
是 TCP Segment 的長度 (表頭+資料),
並且它不包含虛擬表頭的 12 個位元組。
虛擬表頭 (Pseudo-Header) — IPv6
當然啦,若使用的不是 32 位元的 IPv4 位址,
而是 128 位元的 IPv6 位址,虛擬表頭 也會有所改變。
- 來源位址 (Source Address) 與 目的位址 (Destination Address):
不再是 IPv4 的 32 位元 (4 位元組),
而是 IPv6 的 128 位元 (16 位元組) - Zero:
顧名思義 (00000000 00000000 00000000)
(3 位元組) - PTCL:
一樣,TCP 為 6,UDP 為 17。
(1 位元組) - TCP Length:
是 TCP Segment 的長度 (表頭+資料),
並且它不包含虛擬表頭的 40 個位元組。
(4 位元組)
TCP/IPv4 虛擬表頭,為 12 個位元組 (octet),
TCP/IPv6 虛擬表頭,為 40 個位元組 (16+16+3+1+4)。
計算方式 — 發送方
- 若為 發送方,必須先 清除 Checksum 欄位,以產生 Checksum 值。
- 將欲計算檢驗和的相鄰位元組,配對為 16-bit 整數,
包含 虛擬表頭 (Pseudo-Header)、TCP 區段 (表頭+資料),
當然也包含 Checksum 欄位 (發送方會先清空),
若資料長度為奇數,則暫時填補 1 個全部為 0 的位元組。 - 形成這些 16-bit 整數的 1 的補數和 (1’s complement sum)。
- 將此 『 1 的補數和 』經過 『 1 的補數 』運算後,
放入 Checksum 欄位中。
簡單說就是:
The checksum field is the 16 bit one’s complement of the
one’s complement sum of all 16 bit words in the header and text.
計算方式 — 接收方
接收方 與 發送方計算方式如出一徹,
唯一不同在於,不需清除收到的 Checksum 欄位 (因為要透過它來檢查 😅),
算出來的 『1 的補數和』 ,若為 1111 1111 … 1111,
或是 Checksum 值,為 0000 0000 … 0000,
即表示驗證成功,反之。
至於,為什麼算出來的值,會是 0000..?
假設:
發送方 經過 步驟『1』、『2』、『3』:
利用 『 1 的補數和 』算出包含 虛擬表頭 (Pseudo-Header)、TCP 區段 (表頭+資料),
其值為: 『 0111 』(實際上,當然不是 4 位元,僅為理解用)。
TCP 區段 (TCP Segment):
接著,經由 步驟『4』:
經過 『 1 的補數 』運算後,
算出 Checksum 欄位為: 『 1000 』。
如果區段沒有問題,那 接收方 經過 『1』、『2』、『3』步驟,
所算出的 1 的補數和 就會為: 『 0111 』+『 1000 』= 『 1111 』,
最後,經由 步驟『4』:
經過 『 1 的補數 』運算 『 1111 』後,
當然就是: 『 0000 』啦 !