TCP粘包,拆包及解決方法

2021-10-06 04:20:42 字數 1775 閱讀 3948

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

第一種情況,接收端正常收到兩個資料報,即沒有發生拆包和粘包的現象

第二種情況,接收端只收到乙個資料報,由於tcp是不會出現丟包的,所以這乙個資料報中包含了傳送端傳送的兩個資料報的資訊,這種現象即為粘包。這種情況由於接收端不知道這兩個資料報的界限,所以對於接收端來說很難處理

第三種情況,這種情況服務端一共收到了兩個資料報,第乙個資料報只包含了第一條訊息的一部分,第一條訊息的後半部分和第二條訊息都在第二個資料報中,或者是第乙個資料報包含了第一條訊息的完整資訊和第二條訊息的一部分資訊,第二個資料報包含了第二條訊息的剩下部分,這種情況其實是發生了tcp拆包,因為發生了一條訊息被拆分在兩個包裡面傳送了,同樣上面的伺服器邏輯對於這種情況是不好處理的

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

tcp屬於傳輸層的協議,傳輸層除了有tcp協議外還有udp協議,但是udp不會發生粘包或拆包的現象,因為udp是基於報文傳送的,從udp的幀結構可以看出,在udp首部採用了16bit來指示udp資料報文的長度,因此在應用層能很好的將不同的資料報文區分開,從而避免粘包和拆包的問題。而tcp是基於位元組流的,雖然應用層和tcp傳輸層之間的資料互動是大小不等的資料塊,但是tcp把這些資料塊僅僅看成一連串無結構的位元組流,沒有邊界;另外從tcp的幀結構也可以看出,在tcp的首部沒有表示資料長度的字段,基於上面兩點,在使用tcp傳輸資料時,才有粘包或者拆包現象發生的可能。

發生tcp粘包或拆包有很多原因,現列出常見的幾點:

1、要傳送的資料大於tcp傳送緩衝區剩餘空間大小,將會發生拆包

2、待傳送資料大於mss(最大報文長度),tcp在傳輸前將進行拆包

3、要傳送的資料小於tcp傳送緩衝區的大小,tcp將多次寫入緩衝區的資料一次傳送出去,將會發生粘包

4、接收資料端的應用層沒有及時讀取接收緩衝區中的資料,將發生粘包

解決問題的關鍵在於如何給每個資料報新增邊界資訊,常用的方法有如下幾個:

1、傳送端給每個資料報新增包首部,首部中應該至少包含資料報的長度,這樣接收端在接收到資料後,通過讀取包首部的長度字段,便知道每乙個資料報的實際長度了

2、傳送端將每個資料報封裝為固定長度(不夠的可以通過補0填充),這樣接收端每次從接收緩衝區中讀取固定長度的資料就自然而然的把每個資料報拆分開來

3、可以在資料報之間設定邊界,如新增特殊符號,這樣,接收端通過這個邊界就可以將不同的資料報拆分開

使用兩種方法來解決粘包和拆包問題,固定資料報長度和新增長度首部,這兩種方法各有優劣。固定資料報長度傳輸效率一般,尤其是在要傳送的資料長度長短差別很大的時候效率會比較低,但是程式設計實現比較簡單;新增長度首部雖然可以獲得較高的傳輸效率,冗餘資訊少且固定,但是程式設計實現較為複雜。

固定資料報長度

這種處理方式的思路很簡單,傳送端在傳送實際資料前先把資料封裝為固定長度,然後在傳送出去,接收端接收到資料後按照這個固定長度進行拆分即可。

新增長度首部

這種方式的處理較上面提到的方式稍微複雜一點。在傳送端需要給待傳送的資料新增固定的首部,然後再傳送出去,然後在接收端需要根據這個首部的長度資訊進行資料報的組合或拆分。傳送端在傳送資料前首先給待傳送資料新增了代表長度的首部,首部長為4bytes(即int型長度),這樣接收端在收到這個資料之後,首先需要讀取首部,拿到實際資料長度,然後再繼續讀取實際長度的資料,即實現了組包和拆包的操作。可以很明顯的感覺到這種方法的處理難度相對於固定長度要大一些,不過這種方式可以獲取更大的傳輸效率。

TCP粘包,拆包及解決方法

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

TCP粘包,拆包及解決方法

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

TCP粘包,拆包及解決方法

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