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

                                                   


       发送粘包或接收缓存区积压,但用户缓冲区大于接收缓存区数据包总大小。此时须要考虑处理一次处理多数据包的状况,但每一个数据包都是完整的。
调试

                                              


       发送粘包或接收缓存区积压, 用户缓存区是数据包大小的整数倍。 此时须要考虑处理一次处理多数据包的状况,但每一个数据包都是完整的。效率

                             


       发送粘包或接收缓存区积压, 用户缓存区不是数据包大小的整数倍。 此时须要考虑处理一次处理多数据包的状况,同时也须要考虑数据包不完整。原理

                                


       咱们的状况就属于最后一种,发生了数据包不完整的状况。


       就两种状况下会发生粘包:

  • 发送端须要等缓冲区满才发送出去,形成粘包;
  • 接收方不及时接收缓冲区的包,形成多个包接收。
相关文章
相关标签/搜索