Qt通过UDP传图片,实现自定义分包和组包
一.包头结构体
- //包头
- 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的评论
http://blog.csdn.net/caoshangpa/article/details/52681572
Qt通过UDP传图片,实现自定义分包和组包的更多相关文章
- 异步SOCKET分包和组包的一种通用算法
unit uPackage;// 应用协议// cxg 2016-9-23// 包=包头+包体 interface uses SysUtils, Classes, PeachCtrl.Net.Iocp ...
- Socket之UDP分包组包
一般传输大的文件和信息的时候需要涉及到分包和组包,方法有很多,下面一种是借鉴了别人的思路,供大家参考哈 分包 1.取出需要传输的文件和字符的长度和大小放入缓存区里面: 2.设定固定传输的长度,用需要传 ...
- 使用 Qt 获取 UDP 数据并显示成图片
一个项目,要接收 UDP 数据包,解析并获取其中的数据,主要根据解析出来的行号和序号将数据拼接起来,然后将拼接起来的数据(最重要的数据是 R.G.B 三个通道的像素值)显示在窗口中.考虑到每秒钟要接收 ...
- 使用 Qt 获取 UDP 数据并显示成图片(2)
本文首发于 BriFuture 的 个人博客 在我的前一篇文章 使用 Qt 获取 UDP 数据并显示成图片 中,我讲了如何用 Python 模拟发送数据,如何在 Qt 中高效的接收 UDP 数据包并将 ...
- 7.Vue-Quill-Editor图片插入自定义
Vue-Quill-Editor图片插入自定义 前言: 因为在项目中前端采用了Vue来实现,正好用到了富文本编辑器这一块,于是,经过技术上的选择,决定使用Vue-Quill-Editor. 使用的过程 ...
- Qt自适应大小显示图片,添加菜单
由于后面的图像处理需要UI,OpenCV自带也不怎么会,MFC实在懒得学的.听同学说Qt不错,就用Qt做UI了. 本文主要介绍三个内容:在Qt Creator中使用OpenCV2.Qt中自适应显示图片 ...
- iOS开发——UI进阶篇(十八)核心动画小例子,转盘(裁剪图片、自定义按钮、旋转)图片折叠、音量震动条、倒影、粒子效果
一.转盘(裁剪图片.自定义按钮.旋转) 1.裁剪图片 将一张大图片裁剪为多张 // CGImageCreateWithImageInRect:用来裁剪图片 // image:需要裁剪的图片 // re ...
- 用qt代码怎样编写图片保存格式[qt4.6]
用qt代码怎样编写图片保存格式 qt提供了多个保存图片的接口,比较常用的接口如下 bool QPixmap::save ( const QString & fileName, const ch ...
- iOS-AFNetworking-上传图片
一.AFNetworking上传图片 /** 需要Demo,可留言 */ 1.利用AFnetworking上传图片. 2.注意将UIImage类型转化为NSData类型,传给后台. 二.Demo // ...
随机推荐
- 替换APK中的jar包文件
[Qboy] 2014年12月21日 这几天,我第一次做的android游戏(WE!青春纪)马上就要上线.上线之前需要把各个渠道的SDK加入到我们游戏中,与渠道进行联运.但是商务很给力,一下子联系了1 ...
- Oracle 11g 11201_RHEL5.5_RAC_VBOX 详细搭建步骤
1.安装好vbox,创建好虚拟机(红帽5.5),注意:VBOX全局设置VBOX磁盘的位置和备份位置 IP.hostname 规划: hostname ...
- 将centos系统中的网卡em1还原为eth0
1.修改系统grub 操作:vi /boot/grub/grub.conf 增加一个 biosdevname=0 的启动参数 示例: [root@xingfujie ~]# cat /boot/gru ...
- 团队项目--“我爱淘”校园二手书店 NABC分析
本项目的特点之一:可查询功能 NABC分析: N(Need):方便校园里的学生查找自己需要的二手书籍,免了同学想买二手书还得跑到阿姨那里去看. A(Approach):将学生的信息和书籍的信息都存放在 ...
- Careercup - Google面试题 - 5765091433644032
2014-05-08 09:32 题目链接 原题: Given a binary tree, how would you copy it from one machine to the other, ...
- android讯飞语音开发常遇到的问题
场景:android项目中共使用了3个语音组件:在线语音听写.离线语音合成.离线语音识别 11208:遇到这个错误,授权应用失败,先检查装机量(3台测试权限),以及appid的申请时间(35天期限), ...
- SqlServer Split函数
Create FUNCTION [dbo].[SplitToTable] ( @SplitString nvarchar(max), @Separator nvarchar(10)=' ' ) RET ...
- 中断(interrupt)、异常(exception)、陷入(trap)
原文出处:http://lhk518.blog.163.com/blog/static/3153998320084263554749/ 中断:是为了设备与CPU之间的通信.典型的有如服务请求,任务完成 ...
- poj 3237 Tree 树链剖分
题目链接:http://poj.org/problem?id=3237 You are given a tree with N nodes. The tree’s nodes are numbered ...
- 科学技术法转成BigDemcial
目的:将类似“-412615050624334534247E-3”转成“-412615050624334534.247” 工具:用到BigDemcial Code: public static voi ...