关于TCP单包数据大于1460字节会被拆包的问题
1、问题背景:
最近在用STM32+W5500做项目,需要STM32通过TCP协议发送数据到上位机并显示。当数据量小的时候上位机显示正常,一旦数据量大过大上位机就会出现数据丢失的情况,甚至数据直接不刷新。
2、问题分析过程:
出现这个问题首先排查了一下代码,看看上报协议、帧头、帧尾、数据长度等有没有问题,看了一圈没发现问题,那就直接上wireshark抓包看吧。打开Wireshark看了下数据上报频率,每秒都上报了,符合预期。但是仔细看了一下数据长度,每包都不超过1460字节,而且自己明明控制的是每秒发一包数据,但抓包结果看有时候每秒会有两三包。结合现象,推测数据是被分包了,把每秒的多包数据拼接起来后,发现刚好可以组成一包完整的数据,问题原因这就找到了。
3、问题原因:
我上报数据的格式是:帧头(帧头标识+数据长度+设备个数...)+数据+结束标志。从上面的现象推测:上位机应该是根据我的包头去解析数据的,当数据被拆包以后帧头的数据长度和上位实际接受的数据长度对不上,所以数据被废弃了。
于是上网搜了一下TCP 1460,了解到TCP协议是有这样的分包策略,至于TCP为什么要分包,可以参考下这篇文章,原文链接:https://blog.csdn.net/weixin_52669146/article/details/131665316
当数据包太大无法在网络中一次传输完成时,TCP/IP协议会将数据包分成小块进行传输,这就是分片传输。这样做的原因是因为不同的网络设备或链路有最大传输大小的限制,比如某些网络设备只能接收较小的数据包。
可以把数据包想象成一个大块的蛋糕,而网络设备的MTU就是蛋糕切割的限制。如果蛋糕太大,无法放进一个盘子里,我们就需要将蛋糕切成小块,适应盘子的大小。同样道理,当数据包超过网络设备的MTU时,我们需要将它分成小块,每块都能适应设备的最大传输限制。
4、相关知识:
MTU:是网络的最大传输单元,通信术语:最大传输单元(Maximum Transmission Unit,MTU)是指一种通信协议的某一层上面所能通过的最大数据包大小(以字节为单位)
UDP 包的大小就应该是 1500 - IP头(20) - UDP头(8) = 1472(Bytes)
TCP 包的大小就应该是 1500 - IP头(20) - TCP头(20) = 1460 (Bytes)
参考链接:https://blog.csdn.net/caoshangpa/article/details/51530685