Qt通过UDP传图片,实现自定义分包和组包
来源:互联网 发布:标准差 知乎 编辑:程序博客网 时间:2024/05/17 20:01
一.包头结构体
//包头struct PackageHeader{ //包头大小(sizeof(PackageHeader)) unsigned int uTransPackageHdrSize; //当前包头的大小(sizeof(PackageHeader)+当前数据包长度) unsigned int uTransPackageSize; //数据的总大小 unsigned int uDataSize; //数据被分成包的个数 unsigned int uDataPackageNum; //数据包当前的帧号 unsigned int uDataPackageCurrIndex; //数据包在整个数据中的偏移 unsigned int uDataPackageOffset;};每包数据由包头和包体组成,包头用于标记每包数据的特征,包体是图片根据指定大小分出的每段数据,这里指定大小为const int UDP_MAX_SIZE=1200。
为何要分包可参考:TCP、UDP数据包大小的限制
二.分包与组包
1.分包
int dataLength=buffer.data().size(); unsigned char *dataBuffer=(unsigned char *)buffer.data().data(); int packetNum = 0; int lastPaketSize = 0; packetNum = dataLength / UDP_MAX_SIZE; lastPaketSize = dataLength % UDP_MAX_SIZE; int currentPacketIndex = 0; if (lastPaketSize != 0) { packetNum = packetNum + 1; } PackageHeader packageHead; packageHead.uTransPackageHdrSize=sizeof(packageHead); packageHead.uDataSize = dataLength; packageHead.uDataPackageNum = packetNum; unsigned char frameBuffer[1024*1000]; memset(frameBuffer,0,1024*1000); while (currentPacketIndex < packetNum) { if (currentPacketIndex < (packetNum-1)) { packageHead.uTransPackageSize = sizeof(PackageHeader)+UDP_MAX_SIZE; packageHead.uDataPackageCurrIndex = currentPacketIndex+1; packageHead.uDataPackageOffset = currentPacketIndex*UDP_MAX_SIZE; memcpy(frameBuffer, &packageHead, sizeof(PackageHeader)); memcpy(frameBuffer+sizeof(PackageHeader), dataBuffer+packageHead.uDataPackageOffset, UDP_MAX_SIZE); int length=udpsocketSend->writeDatagram( (const char*)frameBuffer, packageHead.uTransPackageSize, QHostAddress(ui->lineEditIP->text()), ui->lineEditPort->text().toInt()); if(length!=packageHead.uTransPackageSize) { qDebug()<<"Failed to send image"; } currentPacketIndex++; } else { packageHead.uTransPackageSize = sizeof(PackageHeader)+(dataLength-currentPacketIndex*UDP_MAX_SIZE); packageHead.uDataPackageCurrIndex = currentPacketIndex+1; packageHead.uDataPackageOffset = currentPacketIndex*UDP_MAX_SIZE; memcpy(frameBuffer, &packageHead, sizeof(PackageHeader)); memcpy(frameBuffer+sizeof(PackageHeader), dataBuffer+packageHead.uDataPackageOffset, dataLength-currentPacketIndex*UDP_MAX_SIZE); int length=udpsocketSend->writeDatagram( (const char*)frameBuffer, packageHead.uTransPackageSize, QHostAddress(ui->lineEditIP->text()), ui->lineEditPort->text().toInt()); if(length!=packageHead.uTransPackageSize) { qDebug()<<"Failed to send image"; } currentPacketIndex++; } }先将图片转换为QBuffer,这样就可以获取图片的数据和长度,然后根据指定大小UDP_MAX_SIZE分包。在包头中设置每包数据的特征,然后将包体加到包头后面发送出去。
2.组包
static int num = 1; static uint size = 0; PackageHeader *packageHead = (PackageHeader *)datagram.data(); if (packageHead->uDataPackageCurrIndex == num) { num++; size += packageHead->uTransPackageSize-packageHead->uTransPackageHdrSize; if (size > 1024*1000) { qDebug()<<"image too big"; num = 1; size = 0; return; } if (packageHead->uDataPackageOffset > 1024*1000) { qDebug()<<"image too big"; packageHead->uDataPackageOffset = 0; num = 1; size = 0; return; } memcpy(imageData.data+packageHead->uDataPackageOffset, datagram.data()+packageHead->uTransPackageHdrSize, packageHead->uTransPackageSize-packageHead->uTransPackageHdrSize); if ((packageHead->uDataPackageNum == packageHead->uDataPackageCurrIndex) && (size == packageHead->uDataSize)) { imageData.length = packageHead->uDataSize; QImage image; image.loadFromData((uchar *)imageData.data,imageData.length,"JPG"); QPixmap pixmap=QPixmap::fromImage(image); ui->labelImage_2->setPixmap(pixmap); recvImageNum++; ui->lineEditRevFrame->setText(QString::number(recvImageNum)); ui->lineEditRevSize->setText(QString::number(imageData.length)); memset(&imageData,0,sizeof(UdpUnpackData)); num = 1; size = 0; } } else { num = 1; size = 0; memset(&imageData,0,sizeof(UdpUnpackData)); }组包是分包的逆过程,根据包头中“数据的总大小”和“数据被分成包的个数”两个字段可以判断组包是否完整,如果完整就在接收端显示出来。
三.示例
界面包括发送端和接收端,接收端的IP地址是自动获取的本机IP地址,上图将发送端的IP地址设置为与接收端IP地址相同,可实现自发自收。
每秒帧数可实时设置每秒发送图片的张数,发送帧数表示一共发送了多少张,接收帧数表示一共接收了多少张,图片大小表示每张图片多少Byte。
可将示例运行于两台计算机,实现双向收发。
源码链接:见http://blog.csdn.net/caoshangpa/article/details/52681572的评论
4 0
- Qt通过UDP传图片,实现自定义分包和组包
- Qt通过UDP传图片,实现自定义分包和组包
- 【转】C#实现UDP分包组包
- 【转】C#实现UDP数据包大文件分包传输和接收组包
- UDP分包组包的类
- 关于socket 分包和组包
- H264分包组包
- 一个UDP包的固定分包丢包问题
- 简析H264分包组包
- 处理粘包和半包有关问题的socket分包Java实现
- Socket粘包,分包解决方法和算法
- TCP的粘包和分包
- scoket如何处理粘包和分包
- 通过自定义View实现圆形图片
- 分包图片
- Qt-----实现Udp通信
- UDP分包重组算法和 基于RTP的H264视频数据分包重组
- UDP分包重组算法
- yum 安装Tomcat7
- Codeforces Round #373 (Div. 2)-B. Anatoly and Cockroaches
- java中非阻塞网络编程中NIO知识点介绍
- 父容器onTouch和子View的OnClick兼容解决,定制特殊刷新,底部回弹
- 几种c/c++中字符串转整形的方法
- Qt通过UDP传图片,实现自定义分包和组包
- 如何在activity和fragment获取控件的大小
- jquery 定义对象并进行操作
- | 是逻辑变量的运算,取“或”,|| 则是布尔变量的运算,取“或”
- HttpURLConnection post解析
- java至今所学的关键词
- ssh登录缓慢
- sql Server Profiler (sql2005为列)
- web测试方法总结