文章插图
UDP(user datagram protocol,用户数据报协议)是无连接的,面向消息的,提供高效率服务 。不会使用块的合并优化算,, 由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了 。即面向消息的通信是有消息保护边界的 。
TCP(transport control protocol,传输控制协议)是面向连接的,面向流的,提供高可靠性服务 。收发两端(客户端和服务器端)都要有一一成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包 。这样,接收端,就难于分辨出来了,必须提供科学的拆包机制 。即面向流的通信是无消息保护边界的 。
1 TCP粘包、拆包图解
文章插图
假设客户端分别发送了两个数据包D1和D2给服务端,由于服务端一次读取到字节数是不确定的,故可能存在以下四种情况:
- 服务端分两次读取到了两个独立的数据包,分别是D1和D2,没有粘包和拆包
- 服务端一次接受到了两个数据包,D1和D2粘合在一起,称之为TCP粘包
- 服务端分两次读取到了数据包,第一次读取到了完整的D1包和D2包的部分内容,第二次读取到了D2包的剩余内容,这称之为TCP拆包
- 服务端分两次读取到了数据包,第一次读取到了D1包的部分内容D1_1,第二次读取到了D1包的剩余部分内容D1_2和完整的D2包 。
2 发生原因
- socket缓冲区与滑动窗口
- MSS/MTU限制
- Nagle算法
https://zhuanlan.zhihu.com/p/103616849
3 解决方案:定义通信协议通过定义应用的协议(protocol)来解决 。协议的作用就定义传输数据的格式 。这样在接受到的数据的时候,如果粘包了,就可以根据这个格式来区分不同的包,如果拆包了,就等待数据可以构成一个完整的消息来处理 。目前业界主流的协议(protocol)方案可以归纳如下:
1 定长协议:假设我们规定每3个字节,表示一个有效报文,如果我们分4次总共发送以下9个字节:
+---+----+------+----+ | A | BC | DEFG | HI | +---+----+------+----+
那么根据协议,我们可以判断出来,这里包含了3个有效的请求报文 +-----+-----+-----+ | ABC | DEF | GHI | +-----+-----+-----+
2 特殊字符分隔符协议:在包尾部增加回车或者空格符等特殊字符进行分割。例如,按行解析,遇到字符n、rn的时候,就认为是一个完整的数据包 。对于以下二进制字节流:
+--------------+ | ABCnDEFrn | +--------------+
那么根据协议,我们可以判断出来,这里包含了2个有效的请求报文 +-----+-----+ | ABC | DEF | +-----+-----+
3 长度编码:将消息分为消息头和消息体,消息头中用一个int型数据(4字节),表示消息体长度的字段 。在解析时,先读取内容长度Length,其值为实际消息体内容(Content)占用的字节数,之后必须读取到这么多字节的内容,才认为是一个完整的数据报文 。 headerbody+--------+----------+| Length | Content |+--------+----------+
总的来说,通信协议就是通信双方约定好的数据格式,发送方按照这个数据格式来发送,接受方按照这个格式来解析 。因此发送方和接收方要完成的工作不同,发送方要将发送的数据转换成协议规定的格式,称之为编码(encode);接收方需要根据协议的格式,对二进制数据进行解析,称之为解码(decode) 。【TCP粘包、拆包与解决方案】
推荐阅读
- ICMP ARP协议 TCP&UDP协议相关介绍,两分钟快速掌握
- 中医提醒!中草药茶不宜长期饮用
- 常喝菊花茶可致体质虚寒、免疫力下降
- 教你买最便宜的机票
- 手电钻、冲击钻、电锤、电起子有什么区别?一文搞懂男人电钻工具
- 棉被、羽绒被哪个更保暖?听内行人说完,才知道我家一直选错了
- 百度文库如何注册、下载、上传、排名、引流推广和赚钱?
- 速读,五分钟深入了解HTTP
- TCP粘包的解决方案
- 饮食新概念:油、茶、饭、水也醉人