TCP粘包, UDP丟包, nagle演算法

2022-03-26 22:32:50 字數 2815 閱讀 7245

一、tcp粘包

1. 什麼時候考慮粘包

如果利用tcp每次傳送資料,就與對方建立連線,然後雙方傳送完一段資料後,就關閉連線,這樣就不會出現粘包問題(因為只有一種包結構,類似於http協議,udp不會出現粘包現象)。關閉連線主要要雙方都傳送close連線(參考tcp關閉協議)。如:a需要傳送一段字串給b,那麼a與b建立連線,然後傳送雙方都預設好的協議字元如"hello give me sth abour yourself",然後b收到報文後,就將緩衝區資料接收,然後關閉連線,這樣粘包問題不用考慮到,因為大家都知道是傳送一段字元。

如果傳送資料無結構,如檔案傳輸,這樣傳送方只管傳送,接收方只管接收儲存就ok,也不用考慮粘包

如果雙方建立連線,需要在連線後一段時間內傳送不同結構資料,如連線後,有好幾種結構: 1)"hello give me sth abour yourself"  2)"don『t give me sth abour yourself"  那這樣的話,如果傳送方連續傳送這個兩個包出去,接收方一次接收可能會是"hello give me sth abour yourselfdon『t give me sth abour yourself" 這樣接收方就傻了,到底是要幹嘛?不知道,因為協議沒有規定這麼詭異的字串,所以要處理把它分包,怎麼分也需要雙方組織乙個比較好的包結構,所以一般可能會在頭加乙個資料長度之類的包,以確保接收。

4.粘包、拆包問題說明

假設客戶端分別傳送資料報d1和d2給服務端,由於服務端一次性讀取到的位元組數是不確定的,所以可能存在以下4種情況。

如果此時服務端tcp接收滑動窗非常小,而資料報d1和d2都很大,很有可能傳送第五種可能,即服務端多次才能把d1和d2接收完全,期間多次發生拆包

tcp的內容)

2. 粘包出現的原因: 

粘包問題是由tcp是「位元組流」協議,沒有訊息邊界所引起的。

在流傳輸中會出現(如tcp),udp不會出現粘包(資料報傳輸)

傳送端需要等緩衝區滿才傳送出去,造成粘包  (nalge演算法也可能造成粘包現象)      接收方不及時接收緩衝區的包,造成多個包接收    

3. 粘包解決的辦法

一是對於傳送方引起的粘包現象,使用者可通過程式設計設定來避免,tcp提供了強制資料立即傳送的操作指令push,tcp軟體收到該操作指令後,就立即將本段資料傳送出去,而不必等待傳送緩衝區滿;

二是對於接收方引起的粘包,則可通過優化程式設計、精簡接收程序工作量、提高接收程序優先順序等措施,使其及時接收資料,從而盡量避免出現粘包現象;

三是由接收方控制,將一包資料按結構字段,人為控制分多次接收,然後合併,通過這種手段來避免粘包。

還有的笨方法是在兩次send函式之間新增 sleep函式, 顯然會降低資料傳輸效率

以上提到的三種措施,都有其不足之處。

第一種程式設計設定方法雖然可以避免傳送方引起的粘包,但它關閉了優化演算法,降低了網路傳送效率,影響應用程式的效能,一般不建議使用。

第二種方法只能減少出現粘包的可能性,但並不能完全避免粘包,當傳送頻率較高時,或由於網路突發可能使某個時間段資料報到達接收方較快,接收方還是有可能來不及接收,從而導致粘包。

第三種方法雖然避免了粘包,但應用程式的效率較低,對實時應用的場合不適合。

4.  解決粘包的工程方法:

由於底層的tcp無法理解上層的業務邏輯,所以在底層是無法確保資料報不被拆分和重組的,這個問題只能通過上層的應用協議棧設計來解決,根據業界的主流協議的解決方案,歸納如下:

由應用層進行分包處理,本質上就是由應用層來維護訊息和訊息的邊界。

上面處理tcp粘包的方案: 存在不同程度的硬傷 , 在工程上並不適用,工程專案中,根據資料傳輸的特點,推薦兩種可選擇的方案:

1. 新增標誌字段,在每次傳送資料是新增標記字段:a: =>size 標記資料長度的方式  b:特定標記字段標記資料的結尾(模仿幀的設計方式)=>結束符的方式

2. 定義應用層的資料通訊協議 :=>如果資料按照一定的方式儲存或著優加密的需求, 可以通過自己定製 資料通訊協議對資料封裝,並實現自己的資料 封包| 拆包函式。

細節: 

1. 環形緩衝實現方案是定義兩個指標,分別指向有效資料的頭和尾.在存放資料和刪除資料時只是進行頭尾指標的移動.

二、udp丟包

1.丟包的主要原因

接收端處理時間過長導致丟包:呼叫recv方法接收端收到資料後,處理資料花了一些時間,處理完後再次呼叫recv方法,在這二次呼叫間隔裡,發過來的包可能丟失。對於這種情況可以修改接收端,將包接收後存入乙個緩衝區,然後迅速返回繼續recv.

傳送的包較大,超過接受者快取導致丟包:包超過mtu size數倍,幾個大的udp包可能會超過接收者的緩衝,導致丟包

傳送的包頻率太快:雖然每個包的大小都小於mtu size 但是頻率太快

2. 解決方案

1 模擬tcp三次握手協議,通過使用timer定時器監視傳送請求後接受資料的時間,如果一段時間內沒有接受到資料報則判定丟包,並重新傳送本次請求

2. 換tcp 

三、nagle演算法

四、長鏈結  vs 短鏈結

1.長連線

client方與server方先建立通訊連線,連線建立後不斷開, 然後再進行報文傳送和接收。

2.短連線

client方與server每進行一次報文收發交易時才進行通訊連線,交易完畢後立即斷開連線。此種方式常用於一點對多點 

TCP粘包 拆包

tcp粘包 拆包 客戶端發服務端傳送了兩個資料報a和b 粘包 服務端一次性接收到了a和b 拆包 服務端第一次接收了a和b的一部分,第二次接收到了b的剩餘部分 粘包 拆包原因 1 應用程式寫入的位元組大小 socket傳送緩衝區大小 2 tcp分段 tcp data部分的大小 mss max segm...

TCP粘包,拆包

粘包 拆包表現形式 現在假設客戶端向服務端連續傳送了兩個資料報,用packet1和packet2來表示,那麼服務端收到的資料可以分為三種,現列舉如下 第一種情況,接收端正常收到兩個資料報,即沒有發生拆包和粘包的現象,此種情況不在本文的討論範圍內。第二種情況,接收端只收到乙個資料報,由於tcp是不會出...

TCP粘包 拆包

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