粘包產生原因:
先說tcp:由於tcp協議本身的機制(面向連線的可靠地協議-三次握手機制)客戶端與伺服器會維持乙個連線(channel),資料在連線不斷開的情況下,可以持續不斷地將多個資料報發往伺服器,但是如果傳送的網路資料報太小,那麼他本身會啟用nagle演算法(可配置是否啟用)對較小的資料報進行合併(基於此,tcp的網路延遲要udp的高些)然後再傳送(超時或者包大小足夠)。那麼這樣的話,伺服器在接收到訊息(資料流)的時候就無法區分哪些資料報是客戶端自己分開傳送的,這樣產生了粘包;伺服器在接收到資料庫後,放到緩衝區中,如果訊息沒有被及時從快取區取走,下次在取資料的時候可能就會出現一次取出多個資料報的情況,造成粘包現象(確切來講,對於基於tcp協議的應用,不應用包來描述,而應 用 流來描述),個人認為伺服器接收端產生的粘包應該與linux核心處理socket的方式 select輪詢機制的線性掃瞄頻度無關。
再說udp:本身作為無連線的不可靠的傳輸協議(適合頻繁傳送較小的資料報),他不會對資料報進行合併傳送(也就沒有nagle演算法之說了),他直接是一端傳送什麼資料,直接就發出去了,既然他不會對資料合併,每乙個資料報都是完整的(資料+udp頭+ip頭等等發一次資料封裝一次)也就沒有粘包一說了。
分包產生的原因就簡單的多:可能是ip分片傳輸導致的,也可能是傳輸過程中丟失部分包導致出現的半包,還有可能就是乙個包可能被分成了兩次傳輸,在取資料的時候,先取到了一部分(還可能與接收的緩衝區大小有關係),總之就是乙個資料報被分成了多次接收。
解決辦法:
粘包與分包的處理方法:
我根據現有的一些開源資料做了如下總結(常用的解決方案):
乙個是採用分隔符的方式,即我們在封裝要傳輸的資料報的時候,採用固定的符號作為結尾符(資料中不能含結尾符),這樣我們接收到資料後,如果出現結尾標識,即人為的將粘包分開,如果乙個包中沒有出現結尾符,認為出現了分包,則等待下個包中出現後 組合成乙個完整的資料報,這種方式適合於文字傳輸的資料,如採用/r/n之類的分隔符;
另一種是採用在資料報中新增長度的方式,即在資料報中的固定位置封裝資料報的長度資訊(或可計算資料報總長度的資訊),伺服器接收到資料後,先是解析包長度,然後根據包長度擷取資料報(此種方式常出現於自定義協議中),但是有個小問題就是如果客戶端第乙個資料報資料長度封裝的有錯誤,那麼很可能就會導致後面接收到的所有資料報都解析出錯(由於tcp建立連線後流式傳輸機制),只有客戶端關閉連線後重新開啟才可以消除此問題,我在處理這個問題的時候對資料長度做了校驗,會適時的對接收到的有問題的包進行人為的丟棄處理(客戶端有自動重發機制,故而在應用層不會導致資料的不完整性);
粘包和分包
socket通訊時會對傳送的位元組資料進行分包和粘包處理,屬於一種socket內部的優化機制。粘包 當傳送的位元組資料報比較小且頻繁傳送時,socket內部會將位元組資料進行粘包處理,既將頻繁傳送的小位元組資料打包成 乙個整包進行傳送,降低記憶體的消耗。分包 當傳送的位元組資料報比較大時,socke...
Socket粘包分包
粘包和分包問題 1.首先什麼是包 包就是每次伺服器向客戶端傳送的資料每傳送乙個訊息都會被打成乙個包傳送到客戶端。客戶端向伺服器端傳送訊息也是一樣的。2.為什麼會有粘包和分包的問題 是因為sockettcp自身的優化機制所導致的。3.什麼是粘包 粘包就是當伺服器端傳送的資料很小的時候又很頻繁的時候,就...
TCP粘包分包現象
服務端,接收資料,在每次接收到的資料末尾添上乙個 尾 字 客戶端傳送資料,將同樣的資料連續傳送若干次 不是將資料複製若干份一次傳送 using system using system.collections.generic using system.componentmodel using syst...