Qt中关于udp大数据接收问题

十秒耿直拆包选手 2017-10-02 02:52:46
如题,我使用QUdpSocket接收服务器发来的数据,因数据包过大,一个完整的数据可能需要多个udp包。一个完整的udp包中有包头标志位(1个字节长度)、信息长度(2个字节长度,长度包括包头标志位+信息长度)、数据三部分组成。在读取数据时需要对包头标志位进行判别,在信息长度中减去包头标志为和信息长度本身占据的长度,获取实际的数据长度信息并将数据写到文件中。请帮我具体看看代码能否将数据完成读出。
void RadarUdpSocket::readDataFromDCP()
{
QByteArray data_block;
//qDebug() << "***" << endl;

do {
//qDebug() << "---" << endl;
data_block.resize(pendingDatagramSize());
//将数据读取到data_block
readDatagram(data_block.data(), data_block.size());

QDataStream in(&data_block, QIODevice::ReadOnly);
in.setVersion(QDataStream::Qt_5_0);

in >> cat_62_;

//判断欧标标识位
if (CAT_62_ != cat_62_) {
return;
}

in >> block_size_;

//判断数据包是否读取完整,如读取不完整,直接返回继续读取
if (data_block.size() != block_size_) {
return;
}

block_size_ -= 3;
QByteArray block_data;

qint8 ch;
for (int i(0); 0 != block_size_; ++i) {
in >> ch;
block_data.append(ch);
}

//将读取的数据保存到文档中
writeRadarDataToFile(block_data);
} while (hasPendingDatagrams());
}


QFile file(tr("radar_data.txt"));
//文件以WriteOnly&Append模式打开
if ( !file.open(QIODevice::WriteOnly & QIODevice::Append)) {
return;
}

QDataStream write_radar_data(&file);
write_radar_data.setVersion(QDataStream::Qt_5_0);

write_radar_data.writeBytes(bytes, bytes.size());

file.close();
...全文
1836 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
雲天之巔 2017-10-25
  • 打赏
  • 举报
回复
不如看看 rtp这样的协议 都封装好了 直接拿来用多好
  • 打赏
  • 举报
回复
还是自己要定义一套协议。UDP不保证顺序与完整性。 建议每个包头加一个递增的ID,而后在内存里用 std::map 或者QMap进行缓存。 QMap<int, QByteArray> 由于QMap是排序树自组织的,所以顺序就不用管了,插入的时候自动就排好了。只用管是不是丢了。丢了就用自己的协议要求重发某个ID。 而且用QMap的好处,收到几个重复的ID包,会自动保留最新的,覆盖以前的。 确定完整后,直接遍历一遍 foreach,拼接起来就成了。
橙儿稻香 2017-10-07
  • 打赏
  • 举报
回复
本人项目弄过大数据的。。 一般要用TCP传输 要定义一套自己的协议 协议里包含包的ID和大小 我弄得是QT客户端 C语言程序做服务器端 所以没有用QT的数据流QDataStream而是直接write 包的类型是unsigned char 大小刚好是TCP拆分数据包的一个大小 1680字节
zarelaky 2017-10-07
  • 打赏
  • 举报
回复
1,发送的数据可能分多次被读取, 2、建议每次pendingDatagramSize()>0都读取出来,扔到自己的buffer里面,然后在统一计算,拆分
  • 打赏
  • 举报
回复
引用 1 楼 zarelaky 的回复:
你的代码会丢数据, pendingDatagramSize()返回的不一定和你发送数据包大小一样, 建议在接收udp数据时,先将数据读取放置到QByteArray中,当接收数据满足报头定义长度时,再解析数据并写入文件; 另外,数据的接收和写入文件操作,建议分派到两个不同的线程里面做,以防止udp数据量过大时,因系统性能不足以处理而被丢弃,造成数据丢失。
你好,有这么几个问题: 1)“pendingDatagramSize()返回的不一定和你发送数据包大小一样”,你的意思是发送的数据可能分多次读取? 2)在除去报头标志位和信息长度,我通过pendingDatagramSize()和信息长度判断是否读取到全部数据,当(信息长度-3) == pendingDatagramSize()后,我再将数据完整读出?还是必须想你说的收到数据就先读出保存到QByteArray中,同时将未读数据长度减少,当未读数据长度为0时再统一处理数据? 谢谢!
zarelaky 2017-10-06
  • 打赏
  • 举报
回复
你的代码会丢数据, pendingDatagramSize()返回的不一定和你发送数据包大小一样, 建议在接收udp数据时,先将数据读取放置到QByteArray中,当接收数据满足报头定义长度时,再解析数据并写入文件; 另外,数据的接收和写入文件操作,建议分派到两个不同的线程里面做,以防止udp数据量过大时,因系统性能不足以处理而被丢弃,造成数据丢失。

16,199

社区成员

发帖
与我相关
我的任务
社区描述
Qt 是一个跨平台应用程序框架。通过使用 Qt,您可以一次性开发应用程序和用户界面,然后将其部署到多个桌面和嵌入式操作系统,而无需重复编写源代码。
社区管理员
  • Qt
  • 亭台六七座
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧