TCP 粘包拆包
一、什麼是粘包拆包?
粘包拆包是TCP協議傳輸中一種現象概念。TCP是傳輸層協議,他傳輸的是「流」式數據,TCP並不知道傳輸是哪種業務數據,或者說,並不關心。它只是根據緩衝區狀況將數據進行包劃分,然後進行傳輸。
在這個前提下,就有可能發生發生同一個業務數據被分割程多個數據包,或者多個業務數據被打包到同一個數據包進行發送。但是對於業務數據接收方,則必須擁有能夠重新拆解或者組裝完整業務數據的能力。這個現象,我們稱之為TCP粘包拆包。
如上圖,三個業務數據A、B、C被打包成一個數據包進行傳輸;D被分割為連個數據包進行傳輸。
所以綜上,影響粘包拆包發生的原因:
1、業務數據的大小<>TCP 套接字緩衝區大小
如果需要寫入的應用數據大於當前設置的TCP套接字緩衝區,則需要對應用數據進行分次寫入。
SO_SNDBUF:發送緩衝區大小。
SO_RCVBUF:接收緩衝區大小。
應用首先將數據寫入TCP套接字緩衝區,然後等待發送。默認情況下,多數作業系統支援動態調節SO_SNDBUF大小以進行自適應,但是如果有主動設置,則自動調節會失效。
2、MSS大小傳輸線制
標識TCP傳往另一段的最大數據長度,建立連接時,雙發通告自己允許的MSS(只能出現在SYN報文中)。
3、MTU大小限制
網路中主機之間的MTU不是一個常數,取決於所選擇的路由,而且路徑不一定對稱(A到B的選路,B到A的選路).
因為每一次發送報文都會包含IP及TCP首部,所以,發送的報文段越大,效率越高,但是以不發生報文分段及雙方都接受為基礎。否則以較小的MTU發送。
關於MTU MSS相關知識可以參照:MTU(Maximum transmission unit) 最大傳輸單元
二、怎麼處理粘包拆包?
傳輸層是業務無感知的,因此粘包拆包只能由業務層處理。通過指定收發兩端共同的約定規約,發送方按照特定的規則組裝數據,接收方按照同樣的規則拆解數據。
這個共同的約定規約,我們通常稱之為應用層協議;發送方組裝數據的過程稱之為編碼;接收方拆解數據的過程稱之為解碼。
常見的協議處理有如下:
1、固定長度消息
在預知最大報文不超特定長度的情況下,可以規定報文大小固定,業務數據不足則以特定的空間佔位。
2、特定分隔符分割消息
每條消息尾部加特定分割符進行消息分割。
3、消息頭+消息體
每一條消息包含一個消息頭和一個消息體,消息頭使用固定長度佔位,內部寫入當前消息消息體的數據長度。接收方首先讀取消息頭數據,然後根據指明的消息長度進行消息體的讀取。
應用協議沒有統一的規則限制,如上,我們只是簡要說明可能使用的應用協議形式,實際應用中,也會根據特定的場景需求進行定向的優化。