TCP粘包概念、產生原因及解決方法

粘包概念:

  • TCP粘包是指發送方發送的若干包數據到接收方接收時粘成一包,從接收緩衝區看,後一包數據的頭緊接着前一包數據的尾。
  • 粘包可能由發送方造成,也可能由接收方造成。
  • 只有TCP有粘包現象,UDP永遠不會粘包,粘包不一定會發生

粘包原因:

所謂粘包問題主要還是因爲接收方不知道消息之間的界限,不知道一次性提取多少字節的數據所造成的。
• 發送端原因: 由於TCP協議本身的機制(面向連接的可靠地協議-三次握手機制)客戶端與服務器會維持一個連接(Channel),數據在連接不斷開的情況下,可以持續不斷地將多個數據包發往服務器,但是如果發送的網絡數據包太小,那麼他本身會啓用Nagle算法(可配置是否啓用)對較小的數據包進行合併(基於此,TCP的網絡延遲要UDP的高些)然後再發送(超時或者包大小足夠)。那麼這樣的話,服務器在接收到消息(數據流)的時候就無法區分哪些數據包是客戶端自己分開發送的,這樣產生了粘包.
• 接收端原因: 服務器在接收到數據庫後,放到緩衝區中,如果消息沒有被及時從緩存區取走,下次在取數據的時候可能就會出現一次取出多個數據包的情況,造成粘包現象。

什麼時候需要處理粘包現象

  • (1)如果是短連接情況,無需考慮粘包情況
  • (2)如果發送方發送的多個分組本來就是同一個數據的不同部分,比如一個很大的文件被分成多個分組發送,這時,當然不需要處理粘包的現象;例如文件傳輸,只管發送就行,全盤接收存儲即可;
  • (3)但如果多個分組本毫不相干,甚至是並列的關係,我們就一定要處理粘包問題了。比如,我當時- 要接收的每個分組都是一個有固定格式的商品信息,如果不處理粘包問題,每個讀進來的分組我只會處理最前邊的那個商品,後邊的就會被丟棄。這顯然不是我要的結果。基本爲長連接

如何處理粘包現象

(1)發送方

對於發送方造成的粘包現象,我們可以通過關閉Nagle算法來解決,使用TCP_NODELAY選項來關閉Nagle算法。
TCP_NODELAY Nagle詳解 https://blog.csdn.net/lclwjl/article/details/80154565

(2)接收方

遺憾的是TCP並沒有處理接收方粘包現象的機制,我們只能在應用層進行處理。
應用層處理
應用層的處理簡單易行!並且不僅可以解決接收方造成的粘包問題,還能解決發送方造成的粘包問題。
解決方法就是循環處理:應用程序在處理從緩存讀來的分組時,讀完一條數據時,就應該循環讀下一條數據,直到所有的數據都被處理;但是如何判斷每條數據的長度呢?

兩種途徑:

1)格式化數據: 每條數據有固定的格式(開始符、結束符),這種方法簡單易行,但選擇開始符和結束符的時候一定要注意每條數據的內部一定不能出現開始符或結束符;
注意控制符的轉義
2)發送長度: 發送每條數據的時候,將數據的長度一併發送,比如可以選擇每條數據的前4位是數據的長度,應用層處理時可以根據長度來判斷每條數據的開始和結束。

參考TLV 格式及編解碼
TLV一種可變格式,TLV的意思就是:Type類型, Lenght長度,Value值;
Type和Length的長度固定,一般那是2、4個字節;
Value的長度有Length指定;
TLVtag, lengthvalue的縮寫.一個基本的數據元就包括上面三個域. Tag唯一標識該數據元, lengthvalue域的長度. Value就是數據本身了. 舉個例子, 下面是一個tlv格式的AID(應用標識符)字節串”9F06 07A0000000031010”, 其中9F06tag, 07是長度, A0000000031010就是AID本身的值了.

題外話:

其實該命題是個僞問題,TCP是面向字節流的,不存在包這個概念,該問題實際上是TCP數據的無邊界性,是一個應用層的問題

這裏提供一個非常不錯的解釋:
怎麼解決TCP網絡傳輸「粘包」問題?
https://www.zhihu.com/question/20210025/answer/1147479153

順便再看看知乎的討論 https://www.zhihu.com/question/20210025 蠻有意思的的一場辯論

[1] https://www.cnblogs.com/qiaoconglovelife/p/5733247.html

[2] https://www.cnblogs.com/bigox/p/10833462.html

[3] https://www.jianshu.com/p/be45fa5b88d4

[4] https://www.zhihu.com/question/20210025/answer/1147479153

[5] https://www.zhihu.com/question/20210025

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章