前言#
什麼是粘包?為什麼會出現?怎麼解決呢?
1. 什麼是粘包#
- 粘包出現在傳輸層和應用層之間,雖然他們之間的傳輸是一塊一塊的,但是 TCP 將這些一塊塊的數據看成無結構的字節流,沒有邊界
- 從 TCP 的幀結構可以看出,其首部沒有表示數據長度的字段
從上面可看出,粘包就是一個數據包包含了兩個數據包的信息
接收端收到了兩個數據包,但是這兩個數據包要麼是不完整的,要麼就是多出來一塊,這種情況即發生了拆包和粘包。拆包和粘包的問題導致接收端在處理的時候會非常困難,因為無法區分一個完整的數據包。
2. 為什麼會出現粘包#
粘包現象出現在傳輸層 TCP 中
- 發送端出現粘包
當客戶端和伺服器之間傳輸採取 TCP 協議保持長連接狀態時(當然,第一次連接發第一次請求不會出現粘包),但當發送的數據包過於的小時,那麼 TCP 協議默認的會啟用 Nagle 算法,將這些較小的數據包進行合併發送(緩衝區數據發送是一個堆壓的過程);這個合併過程就是在發送緩衝區中進行的,也就是說數據發送出來它已經是粘包的狀態了。 - 接收端出現粘包
接收方採用 TCP 協議接收數據時的過程是這樣的:數據到接收方,從網路模型的下方傳遞至傳輸層,傳輸層的 TCP 協議處理是將其放置接收緩衝區,然後由應用層來主動獲取,這時會出現一個問題,就是我們在程式中呼叫的讀取數據函數不能及時的把緩衝區中的數據拿出來,而下一個數據又到來並有一部分放入的緩衝區末尾,等我們讀取數據時就是一個粘包。(放數據的速度 > 應用層拿數據速度)
3. 怎麼解決拆包和粘包#
分包機制一般有兩個通用的解決方法:
- 特殊字符控制
- 在包頭首都添加數據包的長度。
如果使用 netty 的話,就有專門的編碼器和解碼器解決拆包和粘包問題了。
注意:UDP 沒有粘包問題,但是有丟包和亂序。不完整的包是不會有的,收到的都是完全正確的包。傳送的數據單位協議是 UDP 報文或使用者資料報,發送的時候既不合併,也不拆分。