从Qt的图片文件传输来看Qt 中UDP的收发消息writeDatagram和readDatagram
来源:互联网 发布:淘宝众筹能退款吗 编辑:程序博客网 时间:2024/06/03 13:49
上一篇博客写的是利用Qt的UDP协议传输图片文件。但是有一些问题,比如说还得自己新建一个文件夹存放图片等等。项目想实现的功能是在一个Qt工程的label打开图片文件,另一端就能显示同样的图片,所以加以改进。不需要把接收到的图片写入文件夹中,而是直接把数据都读到picBuffer里面,最后统一显示在label上面。
过程特别曲折,现在也不敢保证完全明白,还望有明白的高人指点。
最开始我写的是这样子的:
发送端:
QString fileName=QFileDialog::getOpenFileName(this,tr("choose image"),".",tr("Images (*.jpg *.png)")); if(fileName.isEmpty()){ return; } QPixmap mPix; mPix.load(fileName); ui->picLabel->setPixmap(mPix); //加载完图片,需要把这张图片传送出去 file.setFileName(fileName); if(!file.open(QIODevice::ReadOnly)) return; QByteArray begin ="Begin!"; PicSocket->writeDatagram(begin,localaddr1,10004);//发送begin表示新的图片开始发送了 while(!file.atEnd()){ QByteArray line = file.read(8000); localaddr1.setAddress("162.105.85.81"); PicSocket->writeDatagram(line,localaddr1,10004); if(line.size()<8000){ QByteArray yes ="End!"; PicSocket->writeDatagram(yes,localaddr1,10004); } }每次读8000字节,直到结束,然后分批次发送给指定的地址和端口。文件发送完毕再发送"End!"表示发送彻底结束。
接收端:
void MainWindow::PicPendingDatagram(){ while(PicSocket->hasPendingDatagrams()){ QByteArray datagram; datagram.resize(PicSocket->pendingDatagramSize()); QHostAddress sender; quint16 Pic_port; PicSocket->readDatagram(datagram.data(),datagram.size(),&sender,&Pic_port); if(datagram=="Begin!"){ picBuffer.clear(); } else if(datagram=="End!"){ showPicture(); break; } else{ picBuffer.append(datagram); } }}void MainWindow::showPicture(){ QBuffer buffer(&picBuffer); buffer.open(QIODevice::ReadOnly); QImageReader reader(&buffer); QImage img =reader.read();
接收端如果接受到begin那么久清空上一次的字符串,接着就开始接收,每次都连在picBuffer的后面,直到接收到“End”那么停止接收,跳出循环。
乍一看没什么不对,但是就是有问题,接收端死活显示不出来图片。于是我做了一些改进,注释掉接收端的break; 这里break是多余的。processPendingDatagram本来就是当端口有数据就会被出发,而hasPendingDatagram是有数据流等待被接收的时候被触发,当发送端发完了没数据了它自动会跳出来,但是还是不行。
void MainWindow::PicPendingDatagram(){ while(PicSocket->hasPendingDatagrams()){ QByteArray datagram; datagram.resize(PicSocket->pendingDatagramSize()); QHostAddress sender; quint16 Pic_port; PicSocket->readDatagram(datagram.data(),datagram.size(),&sender,&Pic_port); if(datagram=="Begin!"){ picBuffer.clear(); } else if(datagram=="End!"){ showPicture(); //break; //注释掉了还是不行。 } else{ picBuffer.append(datagram); } }}
那到底怎么回事?
我把接收端得到的数据的长度打印出来,这时候发现了一些问题。按理来说应该是一些8000后面接一个小于8000的数字,但是实际上输出只有一堆8000,少了最后的一些数据,输出后面接着一句话:Corrupt JPEG data: premature end of data segment. 这是什么意思? 为什么少了很多的数据呢?后面的数据去哪里了?
我猜想是接收的时候,如果发送数据比较快,接收的时候本来一直在hasPendingDatagram()里面循环,但是假设遇到网络问题,突然有一个包有延迟,接收慢了,那么会重新从picPendingDatagram出发,而不是一直在里层循环,这样造成了数据崩溃。因为接收的时候输出有时候能输出3个8000有时候是4个,是变化的,所以我猜测和网络状态有关系。从UDP的触发机制来看,如果有一个包慢了,可能就重新从picPendingDatagram开始写入了,造成错误。
所以我想的是,那么从发送的时候开始,我慢一些,每次都让他在picPendingDatagram触发,而不是从里层的有数据流堆积开始触发,这样数据也不会乱。成功了。在一个端的label控件加载出来的图片,也能显示在另一个端的label上面了。代码如下:
void MainWindow::on_pushButton_clicked(){ QString fileName=QFileDialog::getOpenFileName(this,tr("choose image"),".",tr("Images (*.jpg *.png)")); if(fileName.isEmpty()){ return; } QPixmap mPix; mPix.load(fileName); ui->picLabel->setPixmap(mPix); //加载完图片,需要把这张图片传送出去 file.setFileName(fileName); if(!file.open(QIODevice::ReadOnly)) return; QByteArray begin ="Begin!"; PicSocket->writeDatagram(begin,localaddr1,10004); while(!file.atEnd()){ QByteArray line = file.read(8000); localaddr1.setAddress("162.105.85.81"); PicSocket->writeDatagram(line,localaddr1,10004); _sleep(50);//延迟50ms if(line.size()<8000){ QByteArray yes ="End!"; PicSocket->writeDatagram(yes,localaddr1,10004); qDebug()<<"End!"<<endl; }}我设置每次延迟的参数是50ms,这样每次接收都会认为是从picPendingDatagram开始接收,因为两个包的数据间隔足够长,不会造成数据错乱了。
对于文件这种东西,最好还是用TCP,像UDP这种无确认的,丢包什么的会很难受,图片的话丢了一个包就全显示不出来了。。以及我还是不是很清楚究竟为什么这么做能成功,上面的只是我的猜想。希望各位能提出自己的看法,共同讨论,希望大家不吝赐教啊。。
- 从Qt的图片文件传输来看Qt 中UDP的收发消息writeDatagram和readDatagram
- 在QT下的基于UDP协议的消息收发程序
- QT的文件传输
- 基于UDP的简单收发消息代码
- QT的UDP通信
- Qt的UDP编程
- Qt UDP的使用
- qt 下UDP消息的接收和发送和TCP发送文件
- Qt中UDP协议的使用实例
- Qt中图片的显示
- window QT 环境下编写网络程序(一)---简易的UDP收发程序
- Qt 中如何捕获窗口停用和激活的消息
- Qt 中如何捕获窗口停用和激活的消息
- Qt 中捕获窗口停用和激活的消息 .
- Qt 中捕获窗口停用和激活的消息
- Qt 中如何捕获窗口停用和激活的消息
- QT实现局域网聊天工具(带UDP文件传输)
- QT 编程学习记录のUDP文件传输
- C# 直接创建一个DataTable,并为之添加数据(自定义DataTable)
- Linux shell编程学习笔记(七) 文本编辑
- Android开发之常用的loading等待效果实现,仿微博等待动画。两种实现方式详解
- js倒计时与日期间隔计算
- 2017杭州云栖大会,你带走.club的猴米米了吗?
- 从Qt的图片文件传输来看Qt 中UDP的收发消息writeDatagram和readDatagram
- HotWC3密码经过18年的磨难,今日终于进入公测阶段
- 制度对经济对生活的影响
- idea打war包正确姿势,不要相信网上那些鬼
- c++函数重载
- zookeeper学习记录-09 Zookeeper系统模型
- 十进制转为二进制
- 数字图像处理成长之路15:前景提取(最大似然估计EM算法与高斯混合模型)
- JavaScript权威指南 第一章 代码总结