1. 程式人生 > >Socket TCP粘包拆包

Socket TCP粘包拆包

TCP(transport control protocol,傳輸控制協議)是面向連線的,面向流的,提供高可靠性服務。收發兩端(客戶端和伺服器端)都要有一一成對的socket,因此,傳送端為了將多個發往接收端的包,更有效的發到對方,使用了優化方法(Nagle演算法),將多次間隔較小且資料量小的資料,合併成一個大的資料塊,然後進行封包。這樣,接收端,就難於分辨出來了,必須提供科學的拆包機制。即面向流的通訊是無訊息保護邊界的

UDP(user datagram protocol,使用者資料報協議)是無連線的,面向訊息的,提供高效率服務。不會使用塊的合併優化演算法,, 由於UDP支援的是一對多的模式,所以接收端的skbuff(套接字緩衝區)採用了鏈式結構來記錄每一個到達的UDP包,在每個UDP包中就有了訊息頭(訊息來源地址,埠等資訊),這樣,對於接收端來說,就容易進行區分處理了。 即面向訊息的通訊是有訊息保護邊界的


由於TCP無訊息保護邊界, 需要在訊息接收端處理訊息邊界問題。也就是為什麼我們以前使用UDP沒有此問題。反而使用TCP後,出現少包的現象。

粘包拆包分析

具體分析一下,少包,多包的情況。

正常情況,傳送及時每訊息傳送,接收也不繁忙,及時處理掉訊息。像UDP一樣.


傳送粘包,多次間隔較小且資料量小的資料,合併成一個大的資料塊,然後進行封包. 這種情況和客戶端處理繁忙,接收快取區積壓,使用者一次從接收快取區多個數據包的接收端處理一樣。


傳送粘包或接收快取區積壓,但使用者緩衝區大於接收快取區資料包總大小。此時需要考慮處理一次處理多資料包的情況,但每個資料包都是完整的。


傳送粘包或接收快取區積壓, 使用者快取區是資料包大小的整數倍。此時需要考慮處理一次處理多資料包的情況,但每個資料包都是完整的。


傳送粘包或接收快取區積壓, 使用者快取區不是資料包大小的整數倍。此時需要考慮處理一次處理多資料包的情況,同時也需要考慮資料包不完整。


粘包拆包發生原因


  • 應用程式write寫入的位元組大小 大於 套接字傳送緩衝區大小
  • 進行MSS大小的TCP分段
  • 乙太網楨的paylaod大於MTU進行IP分片

解決粘包拆包

如何應對

  • 不是所有的粘包都需要處理。 我們先列舉一下,免得在編碼過程中,因為知道了粘包的情況下,都處理粘包。
  • 連續的資料流不需要處理。如一個線上視訊,它是一個連續不斷的流, 不需要考慮分包。 
  • 每發一個訊息,建一次連線的情況。 
  • 傳送端使用了TCP強制資料立即傳送的操作指令push。 
  • UDP, 前面已說明白了。在這在強調一下,UDP不需要處理,免的忘記了。