tcp粘包和拆包问题,以及封包和解包方案


参考:

workerman (框架协议源码)

https://blog.csdn.net/msdnwolaile/article/details/50769708 (tcp粘包问题经典分析)

https://wiki.swoole.com/#/learn?id=tcp粘包问题 (swoole文档)

https://www.cnblogs.com/vipstone/p/14239160.html(粘包分包问题解决的3种思路)

粘包与拆包的概念

TCP是基于字节流的,只维护发送出去多少,确认了多少,并没有维护消息与消息之间的边界;

 

在TCP/IP协议中,由于传输层并不了解应用层数据的含义,发送端传输层可能会对应用层数据进行拆分或者合并,在接收端也同样如此。由此而产生的问题就是常常会听说的“粘包与拆包”的问题。

“粘包拆包”的问题在“短报文”和“一问一答”的场景下其实并不会出现。短报文是指报文长度远小于MSS的情况,应用层的报文在TCP报文中完全可以放下。

另一方面,“一问一答”的通信模式可以保证报文会以单一的TCP包发送出去。在这两个条件下都满足时,我们不需要考虑“粘包拆包”问题。

反之,如果这两个条件不同时满足,就很可能会出现“粘包拆包”问题。

粘包的主要原因:

  • 发送方每次写入数据 < 套接字(Socket)缓冲区大小;
  • 接收方读取套接字(Socket)缓冲区数据不够及时。

半包的主要原因:

  • 发送方每次写入数据 > 套接字(Socket)缓冲区大小;
  • 发送的数据大于协议的 MTU (Maximum Transmission Unit,最大传输单元),因此必须拆包。

问题描述,上图

解决方法有三种,具体如下:

1,发送端给每个数据包添加包首部,首部长度应该至少包含数据包的长度 ;

2,固定每次发送的报文长度,不够用0补充;

3,约定好包的边界,添加首部尾部标识,如特许字符;

关键方法

1,封包方法

2,解包方法

3,重要函数和字符

pack(format,arg):将参数打包成二进制字符串

unpack(format,arg):从二进制解析出字符串

ord() 返回字符的ASCII码值

chr() ASCII码值对应的字符,与ord互补
strlen:字符串长度 substr:从某个位置开始截取 strpos:特殊边界字符判断 trim/rtrim/ltrim:去除特殊边界字符

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM