QTCPServer接收同频率QDataStream时单条数据流丢包问题问询
同频率发送QDataStream丢包问题原因解析
核心根本原因
- TCP是面向字节流的传输协议,本身不存在消息边界。当两个10Hz的定时器触发时间高度重合时,两条分别对应Message_Id=2和Message_Id=3的消息会先后写入TCP发送缓冲区,操作系统会将两条小消息合并为一个TCP报文段发送到接收端,也就是常说的TCP粘包现象。
- 你当前接收端的处理逻辑存在缺陷:每次读取到TCP数据后,只解析第一个消息,粘在同一个缓冲区里的其余消息会被直接丢弃:
- 每次
readyRead信号触发时调用tcpServerConnection->readAll()会读走当前内核缓冲区里的所有收到的数据,可能包含多条完整消息 - 你仅对缓冲区里的第一条消息做了解析和处理,剩下的未解析数据会随着下一次
array被重新赋值直接覆盖,所以固定会丢其中一组同频率的消息
- 每次
- 当单条发送、或者各流用随机间隔发送时,两条消息不会被粘在同一个TCP报文中,每次
readAll()刚好仅读到一条完整消息,所以不会出现丢包的假象。
附加代码逻辑错误
你给出的接收端示例代码本身也存在语法+逻辑错误:
// 你的错误顺序:先绑定空array到stream,再给array赋值,stream读取的还是初始的空数据 QByteArray array; QDataStream stream(&array:QIODevice:ReadOnly) array = tcpServerConnection->readAll() // 正确的顺序应该是先读数据,再绑定stream到读取到的array QByteArray array = tcpServerConnection->readAll(); QDataStream stream(&array, QIODevice::ReadOnly);
修复建议
- 定义固定的消息头,包含消息长度字段,每次读取时先读头判断是否收够了一整条消息的长度,再做解析
- 每次解析完一条消息后,判断缓冲区是否还有剩余数据,如果有就继续解析下一条,不要直接丢弃未处理的数据
- 不要依赖发送间隔来避免粘包,TCP协议本身的特性决定了粘包是必然可能出现的,必须在应用层做消息边界处理。
内容的提问来源于stack exchange,提问作者taimoor1990
相关产品推荐
相关产品推荐

