TCP中分包,黏包解決辦法

2021-08-15 20:21:39 字數 1432 閱讀 1889

粘包產生原因:

先說tcp:由於tcp協議本身的機制(面向連線的可靠地協議-三次握手機制)客戶端與伺服器會維持一

個連線(channel),資料在連線不斷開的情況下,可以持續不斷地將多個資料報發往伺服器,但是如

果傳送的網路資料報太小,那麼他本身會啟用nagle演算法(可配置是否啟用)對較小的資料報進行合併

(基於此,tcp的網路延遲要udp的高些)然後再傳送(超時或者包大小足夠)。那麼這樣的話,伺服器

在接收到訊息(資料流)的時候就無法區分哪些資料報是客戶端自己分開傳送的,這樣產生了粘包;服

務器在接收到資料庫後,放到緩衝區中,如果訊息沒有被及時從快取區取走,下次在取資料的時候可能

就會出現一次取出多個資料報的情況,造成粘包現象(確切來講,對於基於tcp協議的應用,不應用包

來描述,而應 用 流來描述),個人認為伺服器接收端產生的粘包應該與linux核心處理socket的方式 

select輪詢機制的線性掃瞄頻度無關。

再說udp:本身作為無連線的不可靠的傳輸協議(適合頻繁傳送較小的資料報),他不會對資料報進行

合併傳送(也就沒有nagle演算法之說了),他直接是一端傳送什麼資料,直接就發出去了,既然他不會

對資料合併,每乙個資料報都是完整的(資料+udp頭+ip頭等等發一次資料封裝一次)也就沒有粘包一

說了。分包產生的原因就簡單的多:可能是ip分片傳輸導致的,也可能是傳輸過程中丟失部分包導致出現的半

包,還有可能就是乙個包可能被分成了兩次傳輸,在取資料的時候,先取到了一部分(還可能與接收的

緩衝區大小有關係),總之就是乙個資料報被分成了多次接收。

解決辦法:

粘包與分包的處理方法:

我根據現有的一些開源資料做了如下總結(常用的解決方案):

乙個是採用分隔符的方式,即我們在封裝要傳輸的資料報的時候,採用固定的符號作為結尾符(資料中

不能含結尾符),這樣我們接收到資料後,如果出現結尾標識,即人為的將粘包分開,如果乙個包中沒

有出現結尾符,認為出現了分包,則等待下個包中出現後 組合成乙個完整的資料報,這種方式適合於

文字傳輸的資料,如採用/r/n之類的分隔符;

另一種是採用在資料報中新增長度的方式,即在資料報中的固定位置封裝資料報的長度資訊(或可計算

資料報總長度的資訊),伺服器接收到資料後,先是解析包長度,然後根據包長度擷取資料報(此種方

式常出現於自定義協議中),但是有個小問題就是如果客戶端第乙個資料報資料長度封裝的有錯誤,那

麼很可能就會導致後面接收到的所有資料報都解析出錯(由於tcp建立連線後流式傳輸機制),只有客

戶端關閉連線後重新開啟才可以消除此問題,我在處理這個問題的時候對資料長度做了校驗,會適時的

對接收到的有問題的包進行人為的丟棄處理(客戶端有自動重發機制,故而在應用層不會導致資料的不

完整性);

另一種不建議的方式是tcp採用短連線處理粘包(這個得根據需要來,所以不建議);

TCP粘包原因及解決辦法

粘包 多個資料報被連續儲存於連續的快取中,在對資料報進行讀取時由於無法確定發生方的傳送邊界,而採用某一估測值大小來進行資料讀出,若雙方的size不一致時就會使指傳送方傳送的若干包資料到接收方接收時粘成一包,從接收緩衝區看,後一包資料的頭緊接著前一包資料的尾。比如說 傳送方傳送了兩個資料,接收方一次收...

TCP的粘包和拆包問題及解決辦法(C )

本文參考 如果客戶端連續不斷的向服務端傳送資料報時,服務端接收的資料會出現兩個資料報粘在一起的情況,這就是tcp協議中經常會遇到的粘包以及拆包的問題。我們都知道tcp屬於傳輸層的協議,傳輸層除了有tcp協議外還有udp協議。tcp tcp是基於位元組流的,雖然應用層和tcp傳輸層之間的資料互動是大小...

TCP的粘包和拆包問題及解決辦法(C )

因此,解決問題的關鍵在於如何給每個資料報新增邊界資訊,基本上有以下三種常見解決辦法 使用第一種方法,寫乙個構造包的類,包括 包頭 資料長度 和包尾 資料 class encodetool 承接上面encodetool類 public static byte decodepacket ref list...