粘包拆包問題是處於網絡比較底層的問題,在數據鏈路層、網絡層以及傳輸層都有可能發生。咱們平常的網絡應用開發大都在傳輸層進行,因爲UDP有消息保護邊界,不會發生粘包拆包問題,所以粘包拆包問題只發生在TCP協議中。html
假設客戶端向服務端連續發送了兩個數據包,用packet1和packet2來表示,那麼服務端收到的數據能夠分爲三種,現列舉以下:服務器
**第一種狀況:**接收端正常收到兩個數據包,即沒有發生拆包和粘包的現象,此種狀況不在本文的討論範圍內。微信
**第二種狀況:**接收端只收到一個數據包,因爲TCP是不會出現丟包的,因此這一個數據包中包含了發送端發送的兩個數據包的信息,這種現象即爲粘包。這種狀況因爲接收端不知道這兩個數據包的界限,因此對於接收端來講很難處理。網絡
**第三種狀況:**這種狀況有兩種表現形式,以下圖。接收端收到了兩個數據包,可是這兩個數據包要麼是不完整的,要麼就是多出來一塊,這種狀況即發生了拆包和粘包。這兩種狀況若是不加特殊處理,對於接收端一樣是很差處理的。ui
發生TCP粘包、拆包主要是因爲下面一些緣由:cdn
應用程序寫入的數據大於套接字緩衝區大小,這將會發生拆包。htm
應用程序寫入數據小於套接字緩衝區大小,網卡將應用屢次寫入的數據發送到網絡上,這將會發生粘包。blog
進行MSS(最大報文長度)大小的TCP分段,當TCP報文長度-TCP頭部長度>MSS的時候將發生拆包。開發
接收方法不及時讀取套接字緩衝區數據,這將發生粘包。get
TCP自己是面向流的,做爲網絡服務器,如何從這源源不斷涌來的數據流中拆分出或者合併出有意義的信息呢?一般會有如下一些經常使用的方法:
一、發送端給每一個數據包添加包首部,首部中應該至少包含數據包的長度,這樣接收端在接收到數據後,經過讀取包首部的長度字段,便知道每個數據包的實際長度了。
二、發送端將每一個數據包封裝爲固定長度(不夠的能夠經過補0填充),這樣接收端每次從接收緩衝區中讀取固定長度的數據就天然而然的把每一個數據包拆分開來。
三、能夠在數據包之間設置邊界,如添加特殊符號,這樣,接收端經過這個邊界就能夠將不一樣的數據包拆分開。
若是你們喜歡個人文章,能夠關注我的訂閱號。歡迎隨時留言、交流。若是想加入微信羣的話一塊兒討論的話,請加管理員簡棧文化-小助手(lastpass4u),他會拉大家進羣。