計算機網路 - TCP粘包、拆包以及解決方案
轉自:http://blog.insanecoder.top/tcp-packet-splice-and-split-issue/
在進行Java NIO學習時,發現,如果客戶端連續不斷的向服務端傳送資料包時,服務端接收的資料會出現兩個資料包粘在一起的情況,這就是TCP協議中經常會遇到的粘包以及拆包的問題。
我們都知道TCP屬於傳輸層的協議,傳輸層除了有TCP協議外還有UDP協議。那麼UDP是否會發生粘包或拆包的現象呢?答案是不會。UDP是基於報文傳送的,從UDP的幀結構可以看出,在UDP首部採用了16bit來指示UDP資料包文的長度,因此在應用層能很好的將不同的資料包文區分開,從而避免粘包和拆包的問題。而TCP是基於位元組流的,雖然應用層和TCP傳輸層之間的資料互動是大小不等的資料塊,但是TCP把這些資料塊僅僅看成一連串無結構的位元組流,沒有邊界;另外從TCP的幀結構也可以看出,在TCP的首部沒有表示資料長度的欄位,基於上面兩點,在使用TCP傳輸資料時,才有粘包或者拆包現象發生的可能。
粘包、拆包表現形式
現在假設客戶端向服務端連續傳送了兩個資料包,用packet1和packet2來表示,那麼服務端收到的資料可以分為三種,現列舉如下:
第一種情況,接收端正常收到兩個資料包,即沒有發生拆包和粘包的現象,此種情況不在本文的討論範圍內。
第二種情況,接收端只收到一個資料包,由於TCP是不會出現丟包的,所以這一個資料包中包含了傳送端傳送的兩個資料包的資訊,這種現象即為粘包。這種情況由於接收端不知道這兩個資料包的界限,所以對於接收端來說很難處理。
第三種情況,這種情況有兩種表現形式,如下圖。接收端收到了兩個資料包,但是這兩個資料包要麼是不完整的,要麼就是多出來一塊,這種情況即發生了拆包和粘包。這兩種情況如果不加特殊處理,對於接收端同樣是不好處理的。
粘包、拆包發生原因
發生TCP粘包或拆包有很多原因,現列出常見的幾點,可能不全面,歡迎補充,
1、要傳送的資料大於TCP傳送緩衝區剩餘空間大小,將會發生拆包。
2、待傳送資料大於MSS(最大報文長度),TCP在傳輸前將進行拆包。
3、要傳送的資料小於TCP傳送緩衝區的大小,TCP將多次寫入緩衝區的資料一次傳送出去(採用Nagle演算法,是TCP為了提高效率),將會發生粘包。
4、接收資料端的應用層沒有及時讀取接收緩衝區中的資料,將發生粘包。
等等。
粘包、拆包解決辦法
通過以上分析,我們清楚了粘包或拆包發生的原因,那麼如何解決這個問題呢?解決問題的關鍵在於如何給每個資料包新增邊界資訊,常用的方法有如下幾個:
1、傳送端給每個資料包新增包首部,首部中應該至少包含資料包的長度,這樣接收端在接收到資料後,通過讀取包首部的長度欄位,便知道每一個資料包的實際長度了。
2、傳送端將每個資料包封裝為固定長度(不夠的可以通過補0填充),這樣接收端每次從接收緩衝區中讀取固定長度的資料就自然而然的把每個資料包拆分開來。
3、可以在資料包之間設定邊界,如新增特殊符號,這樣,接收端通過這個邊界就可以將不同的資料包拆分開。
等等。
附:TCP Nagle演算法的思路: 如果想傳送一個1位元組的業務資料, 還需要加上一些包頭, 實際傳送的資料遠遠大於1位元組, 這樣就很浪費了, 還不如把這帶傳送的n個1位元組業務資料粘起來, 一起傳送。
相關文章
- TCP 粘包 - 拆包問題及解決方案TCP
- 粘包拆包及解決方案
- TCP 粘包拆包TCP
- TCP粘包拆包問題TCP
- TCP的粘包拆包技術TCP
- go語言處理TCP拆包/粘包GoTCP
- Netty解決半包(TCP粘包/拆包導致)讀寫問題NettyTCP
- Netty解決粘包和拆包問題的四種方案Netty
- Netty如何解決粘包拆包?(二)Netty
- Netty(三) 什麼是 TCP 拆、粘包?如何解決?NettyTCP
- Netty - 粘包與拆包Netty
- Netty粘包&半包解決方案Netty
- Netty2:粘包/拆包問題與使用LineBasedFrameDecoder的解決方案Netty
- Netty 中的粘包和拆包Netty
- 粘包/拆包問題一直都存在,只是到TCP就拆不動了。TCP
- 深入學習Netty(5)——Netty是如何解決TCP粘包/拆包問題的?NettyTCP
- 從零開始netty學習筆記之TCP粘包和拆包Netty筆記TCP
- 64行程式碼實現零拷貝go的TCP拆包粘包行程GoTCP
- java nio訊息半包、粘包解決方案Java
- Netty入門系列(2) --使用Netty解決粘包和拆包問題Netty
- Go TCP 粘包問題GoTCP
- TCP協議粘包問題詳解TCP協議
- TCP通訊處理粘包詳解TCP
- Netty中使用MessagePack時的TCP粘包問題與解決方案NettyTCP
- Netty拾遺(七)——粘包與拆包問題Netty
- AS3 TCP Socket 拆包S3TCP
- 詳說tcp粘包和半包TCP
- java nio解決半包 粘包問題Java
- [計算機網路]TCP/IP計算機網路TCP
- 從零開始實現簡單 RPC 框架 7:網路通訊之自定義協議(粘包拆包、編解碼)RPC框架協議
- GO語言手動處理TCP粘包GoTCP
- tcp中的粘包、半包的處理方法TCP
- 硬核圖解TCP粘包 資料包:我只是犯了每個資料包都會犯的錯圖解TCP
- 計算機網路實驗二——利用wireshark抓包計算機網路
- Ixia全新網路操作解決方案可完整探查網路資料包
- netty 解決粘包 和 分包的問題Netty
- [ gev ] Go 語言優雅處理 TCP “粘包”GoTCP
- 計算機網路再次整理————tcp[二]計算機網路TCP