TCP拆包粘包問題

對於剛接觸TCP網絡編程的人有時候碰到一些問題,好比當客服端發送一串消息到服務端,服務端只收到消息的一半,或者當連續發送兩個消息到服務端,服務端同時收到這兩個消息但沒法解析。這就是今天要講的TCP拆包粘包現象。算法

拆包粘包產生的緣由

咱們能夠經過如下圖進行說明編程

1.圖一是正常的狀況下包的發送和接受,客戶端發送p1,p2包,服務端前後接受到p1,p2包,沒有發生粘包和拆包。緩存

2.圖二是發生了拆包的現象。客戶端發送p1,p2包,客戶端對p1拆包分紅p1_1和p1_2,服務端前後收到p1_1,p1_2和p2包。 拆包發生緣由分2種狀況:網絡

  • (1)發送的數據大於套接字緩衝區剩餘大小。
  • (2)發送的數據大於MTU(最大傳輸單元)大小。

在TCP通信協議中TCP的每一個包的頭的長度都是固定的,總長度不能超過MTU(最大傳輸單元),且數據長度不能超過MSS(MSS=MTU-20bytes(IP包頭)-20bytes(TCP包頭))。若是超過了MTU系統會進行拆包處理。以圖二舉個例子:框架

  • (1)假設MTU設置的長度爲1500bytes則MSS爲1460bytes。
  • (2)客戶端發送了p1包數據大小2000bytes。
  • (3)系統判斷總長度超過了MTU大小,須要拆包處理。
  • (4)拆成2個包p1_1和p1_2,p1_1的總長度=1460+20+20=1500,p1_2的總長度=2000-1460+20+20=580。
  • (5)發送包p1_1和包p1_2。

3.圖三是發生了粘包的現象。客戶端發送p1,p2包,p1,p2包到達接收端的緩存,服務端應用讀取緩存時沒法區分p1,p2各自的大小。由於在TCP通信協議中TCP是面向流的,包和包之間沒有界限。粘包可發生在發送端也可發生在接收端以圖三各舉例子:netty

  • (1)發送端緣由致使的粘包,客戶端在發送p1包時,先將p1包放入發送緩存,因爲Nagle算法判斷其發送的可用數據(去頭數據)太小等待一小段時間,這時又發送了p2包,系統將p1和p2合成一個大包發送給服務端。服務端讀到大包,沒法區分p1和p2包。
  • (2)接收端緣由致使的粘包,服務端緩存接收到客戶端發送的p1包,服務端應用未能及時讀取緩存,此時服務端緩存又接收到客戶端發送的p2包,服務端應用讀取緩存,沒法區分p1和p2包。

解決方案

不管拆包仍是粘包本質問題都是沒法區分包界限,解決包界限的問題主要有如下幾種方式:code

  • (1)消息數據的定長,好比定長100字節,不足補空格,接收方收到後解析100字節數據即爲完整數據。但這樣的作的缺點是浪費了部分存儲空間和帶寬。
  • (2)消息數據使用特定分割符區分界限,好比使用換號符號作分割。
  • (3)把消息數據分紅消息頭和消息體,消息頭帶消息的長度,接收方收到後根據消息頭中的長度解析數據。

在實際開發中不少網絡框架對TCP拆包粘包問題的解決作了不少支持,好比netty中LineBasedFrameDecoder解析器就是利用換號符號作分割。blog

相關文章
相關標籤/搜索