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

2022-07-13 15:09:13 字數 2353 閱讀 5265

本文參考:

如果客戶端連續不斷的向服務端傳送資料報時,服務端接收的資料會出現兩個資料報粘在一起的情況,這就是tcp協議中經常會遇到的粘包以及拆包的問題。

我們都知道tcp屬於傳輸層的協議,傳輸層除了有tcp協議外還有udp協議。

tcp

tcp是基於位元組流的,雖然應用層和tcp傳輸層之間的資料互動是大小不等的資料塊,但是tcp把這些資料塊僅僅看成一連串無結構的位元組流,沒有邊界;另外從tcp的幀結構也可以看出,在tcp的首部沒有表示資料長度的字段(也就是說tcp並不知道傳送的單個資料的長度,只要緩衝區空間足夠或是缺少,就有可能發生粘包(和下乙個資料流黏在一起)或拆包(本資料流被拆分)),基於上面兩點,在使用tcp傳輸資料時,才有粘包或者拆包現象發生的可能。

udp

那麼udp是否會發生粘包或拆包的現象呢?答案是不會。udp是基於報文傳送的,從udp的幀結構可以看出,在udp首部採用了16bit來指示udp資料報文的長度,因此在應用層能很好的將不同的資料報文區分開,從而避免粘包和拆包的問題。

打個比方

tcp中傳輸資料位元組流就像是在兩個人之間傳遞水,它們通過乙個容器(緩衝區)來盛裝水,甲連續地向乙傳輸水,如果有兩次的水量剛好可以被容器裝進去那就有可能將兩次的水(資料字節流)放到同乙個容器(緩衝區)中進行傳遞(粘包),如果不夠那麼一次的水可能分兩次傳輸(拆包),基本上有三種情況:

容器》=兩次水量,兩次水量》容器》一次水量,容器《一次水量【要注意每一次的水量可能不一樣】

部分原因

原因並不全面,可能會有其他原因,常見的為上述內容

現在假設客戶端向服務端連續傳送了兩個資料報,用packet1和packet2來表示,那麼服務端收到的資料可以分為三種,

就像上述原因中提到1.tcp是基於位元組流的,雖然應用層和tcp傳輸層之間的資料互動是大小不等的資料塊,但是tcp把這些資料塊僅僅看成一連串無結構的位元組流,沒有邊界;2.另外從tcp的幀結構也可以看出,在tcp的首部沒有表示資料長度的字段(也就是說tcp並不知道傳送的單個資料的長度

因此,解決問題的關鍵在於如何給每個資料報新增邊界資訊,基本上有以下三種常見解決辦法

**

使用第一種方法,寫乙個構造包的類,包括 包頭(資料長度)和包尾(資料)

//

正常情況下

memory ms = new

memorystream(); //

各種流操作

ms.close();//

關閉流​ //

使用using

using (memory ms = new

memorystream())

上面三條的使用流程:

構建包

就是將資料構建為乙個包——包頭(資料長度)+包尾(資料)

class

encodetool

}}

}

解析包

上面講解了如何將資料構建為資料報,那麼如何對這個包進行讀取呢?方法為將資料報按照資料長度來讀取緩衝區中相應長度的資料

//

承接上面encodetool類

public

static

byte decodepacket(ref listcache)

using(memorystream ms = new

memorystream())

//至少包括乙個完整的包

byte data = br.readbytes(length);//

讀取length長度的資料(即解析的資料報中的資料)並儲存至data位元組陣列

//2. 更新資料快取,將被讀取的資料移除,繼續讀取下乙個資料報

cache.clear();//

這裡就是為什麼本方法形參前需要加ref關鍵字的原因

int remainlengthagain = (int)(ms.length - ms.position);//

清空之後重新獲取剩下的資料長度

cache.addrange(br.readbytes(remainlengthagain));//

讀取處已解析資料報外的資料部分並轉移至緩衝區

//3. 返回解析的資料

return

data;

}}

}

TCP粘包和拆包

當傳送包同時傳送兩個資料報時,接收包只收到了乙個資料報,其中包含了兩個資料報的資訊,這種現象為粘包。這種情況下,接收方無法分清兩個資料報的界限,很難處理 當傳送包同時傳送兩個資料報時,接收方也收到了兩個資料報。但是這兩個資料報,乙個是不完整的,乙個是多出來一塊,這種現象為拆包。訊息定長 傳送方將資料...

TCP粘包,拆包及解決方法

假設客戶端向服務端連續傳送了兩個資料報,用packet1和packet2來表示,那麼服務端收到的資料可以分為如下三種 第一種情況,接收端正常收到兩個資料報,即沒有發生拆包和粘包的現象 第二種情況,接收端只收到乙個資料報,由於tcp是不會出現丟包的,所以這乙個資料報中包含了傳送端傳送的兩個資料報的資訊...

TCP粘包,拆包及解決方法

粘包拆包問題是處於網路比較底層的問題,在資料鏈路層 網路層以及傳輸層都有可能發生。我們日常的網路應用開發大都在傳輸層進行,由於udp有訊息保護邊界,不會發生粘包拆包問題,因此粘包拆包問題只發生在tcp協議中。假設客戶端向服務端連續傳送了兩個資料報,用packet1和packet2來表示,那麼服務端收...