UNIX網絡編程——Socket/TCP粘包、多包和少包, 斷包

爲何TCP 會粘包
算法

       前幾天,調試mina的TCP通訊, 第一個協議包解析正常,第二個數據包不完整。爲何會這樣嗎,咱們用mina這樣通訊框架,還會出現這種問題?緩存


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

       UDP(user datagram protocol,用戶數據報協議)是無鏈接的,面向消息的,提供高效率服務。不會使用塊的合併優化算法,, 因爲UDP支持的是一對多的模式,因此接收端的skbuff(套接字緩衝區)採用了鏈式結構來記錄每個到達的UDP包,在每一個UDP包中就有了消息頭(消息來源地址,端口等信息),這樣,對於接收端來講,就容易進行區分處理了。 即面向消息的通訊是有消息保護邊界的框架

       因爲TCP無消息保護邊界, 須要在消息接收端處理消息邊界問題。也就是爲何咱們之前使用UDP沒有此問題。 反而使用TCP後,出現少包的現象socket


粘包的分析
       上面說了原理,但可能有人使用TCP通訊會出現多包/少包,而一些人不會。那麼咱們具體分析一下,少包,多包的狀況。
       正常狀況,發送及時每消息發送,接收也不繁忙,及時處理掉消息。像UDP同樣。
優化

                             


       發送粘包,屢次間隔較小且數據量小的數據,合併成一個大的數據塊,而後進行封包。 這種狀況和客戶端處理繁忙,接收緩存區積壓,用戶一次從接收緩存區多個數據包的接收端處理同樣。spa

                                                   


       發送粘包或接收緩存區積壓,但用戶緩衝區大於接收緩存區數據包總大小。此時須要考慮處理一次處理多數據包的狀況,但每一個數據包都是完整的。
調試

                                              


       發送粘包或接收緩存區積壓, 用戶緩存區是數據包大小的整數倍。 此時須要考慮處理一次處理多數據包的狀況,但每一個數據包都是完整的。效率

                             


       發送粘包或接收緩存區積壓, 用戶緩存區不是數據包大小的整數倍。 此時須要考慮處理一次處理多數據包的狀況,同時也須要考慮數據包不完整。原理

                                


       咱們的狀況就屬於最後一種,發生了數據包不完整的狀況。


       就兩種狀況下會發生粘包:

  • 發送端須要等緩衝區滿才發送出去,形成粘包;
  • 接收方不及時接收緩衝區的包,形成多個包接收。
相關文章
相關標籤/搜索