Qt中udp指令,大小端,帧头帧尾实际示例

前言

        虽然QT中,udp发送和接收,其实非常简单,但是实际工作中,其实涉及到帧头帧尾,字节对齐,以及大小端序的问题。比如网络中,正规的一般都是大端序,而不是小端序,大多数的系统中,默认存储的都是小端序。 其次,udp指令,在代码中,我们一般都会设置结构体,如果是小端可以直接使用结果体转换,如果是大端序,需要先将数据转尾大端然后发送,接收端再将大端序数据转为小端进行分析和保存。以下是一个实际案例的测试demo:

注意:

        以下协议和帧头等都是根据近期项目随机定的,不涉及保密。

        指令接收端口为18000; 目的是开启视频保存。

        

发送端:

main.cpp


#include <QUdpSocket>
#include <QtEndian>
#include <QDataStream>// 以1字节对齐:
#pragma pack(1)
struct SaveVideoCtrlPara
{// 帧头 0xaa56unsigned short dataHead = 0xbb58;// 第一路quint8    video1_isSave       = 0x00;       // 0x00:close    0x01:start savequint8    video1_type         = 0x00;       // 0x00:null     0x01:rtsp        0x02:rtpquint32   video1_para         = 0x00;       // rtsp: IP      rtp :recv portquint32   video1_reserve      = 0x00;       // 预留char      video1_fileName[64] = "";         // 保存文件名// 第一路quint8    video2_isSave       = 0x00;       // 0x00:close    0x01:start savequint8    video2_type         = 0x00;       // 0x00:null     0x01:rtsp        0x02:rtpquint32   video2_para         = 0x00;       // rtsp: IP      rtp :recv portquint32   video2_reserve      = 0x00;       // 预留char      video2_fileName[64] = "";         // 保存文件名// 包尾// unsigned short dataTail = 0x1111;
};
#pragma pack(pop)// 转为大端序
QByteArray serializeStruct(const SaveVideoCtrlPara &data) {QByteArray byteArray;QDataStream stream(&byteArray, QIODevice::WriteOnly);// 将数据转换为大端序stream << qToBigEndian(data.dataHead);stream << qToBigEndian(data.video1_isSave);stream << qToBigEndian(data.video1_type);stream << qToBigEndian(data.video1_para);stream << qToBigEndian(data.video1_reserve);stream << QString(data.video1_fileName).toUtf8();stream << qToBigEndian(data.video2_isSave);stream << qToBigEndian(data.video2_type);stream << qToBigEndian(data.video2_para);stream << qToBigEndian(data.video2_reserve);stream << QString(data.video2_fileName).toUtf8();return byteArray;
}int main(int argc, char *argv[])
{QByteArray temp_byte_array;SaveVideoCtrlPara test;test.video1_type = 0x02;test.video1_para = 10011;strcpy(test.video1_fileName,"test1");test.video2_type = 0x02;test.video2_para = 10012;strcpy(test.video2_fileName,"test2");QUdpSocket *m_pUdpSocket = new QUdpSocket();m_pUdpSocket->bind(QHostAddress("127.0.0.1"),18001);// 小端序// QByteArray frame = QByteArray((char *)&test, sizeof(SaveVideoCtrlPara));// 大端序QByteArray frame = serializeStruct(test);// sendm_pUdpSocket->writeDatagram(frame, QHostAddress("127.0.0.1"), 18000);}

接收端:

main.cpp

#include <QApplication>
#include <QUdpSocket>
#include <QDataStream>
#include <QtEndian>// 以1字节对齐:
#pragma pack(1)
struct SaveVideoCtrlPara
{// 帧头 0xaa56unsigned short dataHead = 0xbb58;// 第一路quint8    video1_isSave       = 0x00;       // 0x00:close    0x01:start savequint8    video1_type         = 0x00;       // 0x00:null     0x01:rtsp        0x02:rtpquint32   video1_para         = 0x00;       // rtsp: IP      rtp :recv portquint32   video1_reserve      = 0x00;       // 预留char      video1_fileName[64] = "";         // 保存文件名// 第一路quint8    video2_isSave       = 0x00;       // 0x00:close    0x01:start savequint8    video2_type         = 0x00;       // 0x00:null     0x01:rtsp        0x02:rtpquint32   video2_para         = 0x00;       // rtsp: IP      rtp :recv portquint32   video2_reserve      = 0x00;       // 预留char      video2_fileName[64] = "";         // 保存文件名// 包尾// unsigned short dataTail = 0x1111;
};
#pragma pack(pop)SaveVideoCtrlPara deserializeStruct(const QByteArray &byteArray)
{QDataStream stream(byteArray);QByteArray tmp_str1,tmp_str2;//tmp_str1.resize(64);//tmp_str2.resize(64);stream.setByteOrder(QDataStream::BigEndian); // 设置为大端序SaveVideoCtrlPara data;// 从数据流中读取并转换为小端序stream >> data.dataHead;stream >> data.video1_isSave;stream >> data.video1_type;stream >> data.video1_para;stream >> data.video1_reserve;stream >> tmp_str1;stream >> data.video2_isSave;stream >> data.video2_type;stream >> data.video2_para;stream >> data.video2_reserve;stream >> tmp_str2;data.dataHead = qFromBigEndian(data.dataHead);data.video1_isSave = qFromBigEndian(data.video1_isSave);data.video1_type = qFromBigEndian(data.video1_type);data.video1_para = qFromBigEndian(data.video1_para);data.video1_reserve = qFromBigEndian(data.video1_reserve);strcpy(data.video1_fileName, tmp_str1.toStdString().c_str());data.video2_isSave = qFromBigEndian(data.video2_isSave);data.video2_type = qFromBigEndian(data.video2_type);data.video2_para = qFromBigEndian(data.video2_para);data.video2_reserve = qFromBigEndian(data.video2_reserve);strcpy(data.video2_fileName, tmp_str2.toStdString().c_str());return data;
}int main(int argc, char *argv[])
{QApplication app(argc, argv);QUdpSocket *m_pUdpSocket = new QUdpSocket();m_pUdpSocket->bind(QHostAddress("127.0.0.1"),18000);QObject::connect(m_pUdpSocket,&QUdpSocket::readyRead,[=](){QByteArray frame;while(m_pUdpSocket->hasPendingDatagrams()){frame.resize(m_pUdpSocket->pendingDatagramSize());// 接收数据报,将其存放到datagram中m_pUdpSocket->readDatagram(frame.data(), frame.size());// 大端序SaveVideoCtrlPara pFrame = deserializeStruct(frame);if(pFrame.dataHead == 0xaa56){qDebug()<<"接收到信息*********";qDebug()<<"video1_isSave:"  <<pFrame.video1_isSave;qDebug()<<"video1_type  :"  <<pFrame.video1_type  ;if(pFrame.video1_type==0x01)qDebug()<<"video1_para  :"  <<QHostAddress(pFrame.video1_para).toString();elseqDebug()<<"video1_para  :"  <<pFrame.video1_para;qDebug()<<"video1_fileName:"<<pFrame.video1_fileName;qDebug()<<"video2_isSave:"  <<pFrame.video2_isSave;qDebug()<<"video2_type  :"  <<pFrame.video2_type  ;if(pFrame.video2_type==0x01)qDebug()<<"video2_para  :"  <<QHostAddress(pFrame.video2_para).toString();elseqDebug()<<"video2_para  :"  <<pFrame.video2_para;qDebug()<<"video2_fileName:"<<pFrame.video2_fileName;qDebug()<<"*****************";}//            // 小端序
//            struct SaveVideoCtrlPara *pFrame = (struct SaveVideoCtrlPara *)frame.data();
//            if(pFrame->dataHead == 0xaa56)
//            {
//                qDebug()<<"接收到信息*********";
//                qDebug()<<"video1_isSave:"  <<pFrame->video1_isSave;
//                qDebug()<<"video1_type  :"  <<pFrame->video1_type  ;
//                if(pFrame->video1_type==0x01)
//                    qDebug()<<"video1_para  :"  <<QHostAddress(pFrame->video1_para).toString();
//                else
//                    qDebug()<<"video1_para  :"  <<pFrame->video1_para;
//                qDebug()<<"video1_fileName:"<<pFrame->video1_fileName;//                qDebug()<<"video2_isSave:"  <<pFrame->video2_isSave;
//                qDebug()<<"video2_type  :"  <<pFrame->video2_type  ;
//                if(pFrame->video2_type==0x01)
//                    qDebug()<<"video2_para  :"  <<QHostAddress(pFrame->video2_para).toString();
//                else
//                    qDebug()<<"video2_para  :"  <<pFrame->video2_para;
//                qDebug()<<"video2_fileName:"<<pFrame->video2_fileName;
//                qDebug()<<"*****************";
//            }}});return app.exec();
}

结论

大端序代码打印结果:

小端序代码打印结果:

        由代码可知,大端序要稍微复杂一些,但是符合互联网传输数据的要求,小端序的实现要简单不少,所以如果是非正规场合,使用小端是一种简洁的方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/866411.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

不到 5 元的随身 WiFi 刷 Debian 系统 做轻量家庭服务器

本文首发于只抄博客,欢迎点击原文链接了解更多内容。 前言 前不久在某宝均价 5 元买了两个随身 WiFi,拆机看了看丝印都是 MSM8916 ,正好是红米 2 同款的骁龙 410 的芯片,可以刷个 Debian 当作家庭服务器来跑一些轻量的服务。 不过手气不是很好,两个都是 512M + 4G 的配置…

单机安装基于LNMP结构的WordPress网站 web与数据库服务分离

网站的类型&#xff1a; Jave:LNMT PHP:LNMP Python: LNMU 项目部署&#xff1a; 1.项目的类型&#xff08;项目的开发语言&#xff09; 2.项目运营平台的技术选择 3.尽快让项目运行起来 all in one部署 4. 架构的优化 配置ansible管理环境 配置nginx 配置数据库服务…

day11_homework_need2submit

Homework 编写—个将ts或mp4中视频文件解码到yuv的程序 yuv数据可以使用如下命令播放: ffplay -i output yuv-pix_fmt yuv420p-s 1024x436 要求: ffmpeg解析到avpacket并打印出pts和dts字段完成解码到avframe并打印任意字段完成yuv数据保存 // teminal orders on bash cd ex…

11.SQL注入-盲注基于(base on boolian)

SQL注入-盲注基于boolian案例利用 首先总结一下sql语句中的函数意思 #查看当前所在的数据库 mysql> select database(); ------------ | database() | ------------ | pikachu | ------------ 1 row in set (0.00 sec)#函数substr里1是从第几位开始取字符&#xff0c;2…

油猴Safari浏览器插件:Tampermonkey for Mac 下载

Tampermonkey 是一个强大的浏览器扩展&#xff0c;用于运行用户脚本&#xff0c;这些脚本可以自定义和增强网页的功能。它允许用户在网页上执行各种自动化任务&#xff0c;比如自动填写表单、移除广告、改变页面布局等。适用浏览器&#xff1a; Tampermonkey 适用于多数主流浏览…

Java的进程和线程

一Java的进程 二Java的线程 多线程 ◆如果在一个进程中同时运行了多个线程&#xff0c;用来完成不同的工作&#xff0c;则称之为“多线程”。 ◆多个线程交替占用CPU资源&#xff0c;而非真正的并行执行。 ◆多线程好处。 ◆充分利用CPU的资源。 ◆简化编程模型。 ◆良好的用…

3-1 激活函数和神经网络思想

3-1 激活函数和神经网络思想 主目录点这里

【抽代复习笔记】26-群(二十):子群的定义以及第一、第二判定定理

子群 定义1&#xff1a;(G,o)是一个群&#xff0c;H是G的非空子集&#xff0c;若H关于G的乘法o也能作成群&#xff08;满足群的判定定理&#xff1a;封闭性、结合律、单位元、逆元&#xff09;&#xff0c;则称H为G的子群&#xff0c;记作H ≤ G&#xff1b;若H是G的真子集&am…

【启明智显分享】手持遥控器HMI解决方案:2.8寸触摸串口屏助力实现智能化

现代生活不少家居不断智能化&#xff0c;但是遥控器却并没有随之升级。在遥控交互上&#xff0c;传统遥控器明显功能不足&#xff1a;特别是大屏智能电视&#xff0c;其功能主要由各种APP程序实现。在电脑上鼠标轻轻点击、在手机上触摸屏丝滑滑动&#xff0c;但是在电视上这些A…

SpringBoot 启动流程二

SpringBoot启动流程二 我们首先查看构造方法 SpringApplication 我们发现这个构造方法还是在SpringApplication类里面 这个构造方法还是调用了自身的构造方法 传入了两个参数 第一个参数叫resourceLoader 传入的是一个资源加载器 要从外部读入东西 这个方法通过this关键字…

c++纵横字谜

1.实现一个纵横字谜 2.支持14x14的网格 3.可以查看答案 4.猜测错误会提示答案信息 5.从txt读取词汇 6.每次游戏开始 随机生成纵横字谜 n’h

leetcode216.组合总和III、40.组合总和II、39.组合总和

216.组合总和III 找出所有相加之和为 n 的 k 个数的组合&#xff0c;且满足下列条件&#xff1a; 只使用数字1到9 每个数字 最多使用一次 返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次&#xff0c;组合可以以任何顺序返回。 示例 1: 输入: k 3, n 7 输出…

deepin UOS AI 如何配置自定义模型

科技飞速发展的今天&#xff0c;操作系统作为计算机系统的灵魂&#xff0c;其每一次的更新与变革都牵动着无数用户的心弦。近日&#xff0c;开源操作系统 deepin 迎来了一次重大更新&#xff0c;这次更新不仅在性能上进行了全面优化&#xff0c;更在 AI 智能化方面迈出了划时代…

【解决方案】笔记本电脑屏幕亮度调节失效(Dell G15 5510 使用Fn调节)

目前解决方案&#xff1a;使用驱动总裁&#xff08;其他的驱动安装软件应该也可以&#xff0c;个人觉得这个好用&#xff09;&#xff0c;更新显卡驱动即可。如图所示本人更新了Intel UHD Graphics核显驱动&#xff0c;功能回复正常。 使用Fn快捷键调节亮度如图所示&#xff0…

ARIES,数据恢复算法,万变不离其宗...

今天来聊两个问题&#xff1a; 1. 如果缓冲池&#xff08;buffer pool&#xff09;满了&#xff0c;哪些数据页&#xff08;page&#xff09;要刷盘&#xff0c;哪些数据页不刷盘&#xff1f; 2. 数据库崩了&#xff0c;怎么利用检查点&#xff08;checkpoint&#xff09;与预写…

Django 定义模型执行迁移

1&#xff0c;创建应用 Test/app8 python manage.py startapp app8 2&#xff0c;注册应用 Test/Test/settings.py 3&#xff0c;配置路由 Test/Test/urls.py from django.contrib import admin from django.urls import path, includeurlpatterns [path(app8/, include(a…

硅纪元视角 | AI纳米机器人突破癌症治疗,精准打击肿瘤细胞

在数字化浪潮的推动下&#xff0c;人工智能&#xff08;AI&#xff09;正成为塑造未来的关键力量。硅纪元视角栏目紧跟AI科技的最新发展&#xff0c;捕捉行业动态&#xff1b;提供深入的新闻解读&#xff0c;助您洞悉技术背后的逻辑&#xff1b;汇聚行业专家的见解&#xff0c;…

Ubuntu24.04之安装KVM(二百五十五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

QT+OpenCV在Android上实现人脸实时检测与目标检测

一、功能介绍 在当今的移动应用领域&#xff0c;随着技术的飞速发展和智能设备的普及&#xff0c;将先进的计算机视觉技术集成到移动平台&#xff0c;特别是Android系统中&#xff0c;已成为提升用户体验、拓展应用功能的关键。其中&#xff0c;目标检测与人脸识别作为计算机视…

Linux—文件内系统与日志分析

目录 一、Linux文件系统 1、inode 与 block概述 1.2、inode内容 1.3、查找inode 1.4、inode故障处理 2、硬盘分区后的结构 3、访问文件的流程 4、文件恢复 4.1、恢复ext3格式文件 4.2、恢复 xfs 格式文件 二、Linux日志文件 1、日志的功能 2、日志的默认位置 3、日…