为何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
发送粘包或接收缓存区积压,但用户缓冲区大于接收缓存区数据包总大小。此时须要考虑处理一次处理多数据包的状况,但每一个数据包都是完整的。
调试
发送粘包或接收缓存区积压, 用户缓存区是数据包大小的整数倍。 此时须要考虑处理一次处理多数据包的状况,但每一个数据包都是完整的。效率
发送粘包或接收缓存区积压, 用户缓存区不是数据包大小的整数倍。 此时须要考虑处理一次处理多数据包的状况,同时也须要考虑数据包不完整。原理
咱们的状况就属于最后一种,发生了数据包不完整的状况。
就两种状况下会发生粘包: