Go TCP 粘包問題

Aliliin發表於2021-12-23

什麼是 TCP 粘包

  • 粘包問題是指當傳送兩條訊息時,比如傳送了 ABC 和 DEF,但另一端接收到的卻是 ABCD,像這種一次性讀取了兩條資料的情況就叫做粘包(正常情況應該是一條一條讀取的),正確讀取 ABC 和 DEF 兩條資訊。

  • 當傳送的訊息是 ABC 時,另一端卻接收到的是 AB 和 C 兩條資訊,像這種情況就叫做半包。

為什麼會有粘包和半包?

  • 這是因為 TCP 是面向連線的傳輸協議,TCP 傳輸的資料是以流的形式,而流資料是沒有明確的開始結尾邊界,所以 TCP 也沒辦法判斷哪一段流屬於一個訊息。

  • 造成粘包的主要原因

    1. 傳送方每次寫入資料 < 套接字(Socket)緩衝區大小

    2. 接收方讀取套接字(Socket)緩衝區資料不夠及時。

  • 造成半包的主要原因

    1. 傳送方每次寫入資料 > 套接字(Socket)緩衝區大小

    2. 傳送的資料大於協議的 MTU (Maximum Transmission Unit,最大傳輸單元),因此必須拆包。

怎麼處理粘包 ?

fix length 處理粘包

執行程式在 client server 目錄

  • 每次傳送固定緩衝區大小資料.客戶端和伺服器約定每次傳送請求的大小.例如客戶端傳送 1024 個位元組,伺服器接受 1024 個位元組。

    這樣雖然可以解決粘包的問題,但是如果傳送的資料小於 1024 個位元組,就會導致資料記憶體冗餘和浪費;且如果傳送請求大於 1024 位元組,會出現半包的問題,也就是資料接收的不完整。

delimiter based 處理粘包

執行程式在 client server 目錄

  • 基於定界符來判斷是不是一個請求(例如結尾’\n’). 客戶端傳送過來的資料,每次以 \n 結束,伺服器每接受到一個 \n 就以此作為一個請求.然後對其拆分後的頭部部分與前一個包的剩餘部分進行合併,這樣就得到了一個完整的包。這種方式的缺點在於如果資料量過大,查詢定界符會消耗一些效能
length field based frame decoder 處理粘包

執行程式在 client server 目錄

  • 在 TCP 協議頭裡面寫入每次傳送請求的長度。 客戶端在協議頭裡面帶入資料長度,伺服器在接收到請求後,根據協議頭裡面的資料長度來決定接受多少資料,只有在讀取到足夠長度的訊息之後才算是讀到了一個完整的訊息。之後會按照引數指定的包長度偏移量資料對接收到的資料進行解碼,從而得到目標訊息體資料。
本作品採用《CC 協議》,轉載必須註明作者和本文連結
高永立

相關文章