1. 程式人生 > >關於TCP黏包問題

關於TCP黏包問題

最近發現自己對於TCP通訊中的黏包問題還有疑問,查閱資料做下總結。
一、TCP黏包問題
TCP黏包問題是因為傳送方把若干資料傳送,接收方收到資料時候黏在一包,從接受緩衝區來看,後一包的資料黏在前一包的尾部。
二、黏包出現的原因
TCP黏包問題主要出現在兩個方面
(1)傳送方問題
首先TCP會預設使用Nagle演算法,Nagle演算法主要做兩件事。
第一:上一包分組得到確認,才會傳送下一分組。
第二:收集多個小組,在一個確認到來時一起傳送。
由此可見Nagle演算法會使得資料在傳送方造成黏包問題 。
(2)接收方問題
TCP接收方接收到分組的時候,並不會立刻提交到應用層處理,收到的資料放在接收快取裡面,然後應用程式會主動從接受快取裡讀取接收的分組,這樣以來,如果TCP接收分組的速度大於應用讀取分組的速度,多個包的資料會存至快取區裡面,應用讀取資料就可能會產生黏包問題。
三、什麼時候處理黏包問題


(1)如果每次利用TCP傳送資料,就與對方建立連線,然後傳送完資料就關閉連線這樣就不會出現黏包問題(大家都知道只發送一個數據包)
(2)如果傳送的資料無結構,比如檔案的傳輸,只要傳送方一直髮送,接收方只管接收到儲存的資料,此時也不用考慮黏包問題。
(3)如果在連線的一段時間內傳送的資料毫無關係,我們就要考慮黏包問題了。
比如:你要傳送一段話
I love you.
I want play.
如果產生了黏包問題,接收方可能會傻眼,你讓我幹啥?所以一般會在資料前加一個長度之類的包,確保接收。
四、處理黏包現象
(1)傳送方
    傳送方產生黏包問題的主要原因在於Nagle演算法,我們可以通過關閉Nagle演算法來解決,使用TCP_NODELAY選項來關閉Nagle演算法。
(2)接收方
    由於TCP沒有處理接收方黏包現象的機制,我們只能在應用層進行處理。
(3)應用層處理
  解決方法就是迴圈處理:應用程式在處理從快取讀來的分組時,讀完一條資料時,就應該迴圈讀下一條資料,直到所有的資料都被處理;但是如何判斷每條資料的長度呢?
  兩種途徑:

    1)格式化資料:每條資料有固定的格式(開始符、結束符),這種方法簡單易行,但選擇開始符和結束符的時候一定要注意每條資料的內部一定不能出現開始符或結束符

    2)傳送長度:傳送每條資料的時候,將資料的長度一併傳送,比如可以選擇每條資料的前4位是資料的長度,應用層處理時可以根據長度來判斷每條資料的開始和結束。