当前位置: 首页 > article >正文

Qt 实现网络数据报文大小端数据的收发

1.大小端数据简介

大小端(Endianness)是计算机体系结构的一个术语,它描述了多字节数据在内存中的存储顺序。以下是大小端的定义和它们的特点:

大端(Big-Endian)
在大端模式中,一个字的最高有效字节(MSB,即最左边的那位)存储在最低的内存地址处,而最低有效字节(LSB,即最右边的那位)存储在最高的内存地址处。

例如,假设有一个16位的数字 0x1234,其在内存中的存储顺序如下:

地址增加方向 -->

[ 12 ] [ 34 ]

其中 [12] 是高字节,存储在低地址处;[34] 是低字节,存储在高地址处。

小端(Little-Endian)
在小端模式中,情况正好相反:一个字的最低有效字节存储在最低的内存地址处,而最高有效字节存储在最高的内存地址处。

继续上面的例子,16位的数字 0x1234 在小端模式下的存储顺序如下:

地址增加方向 -->

[ 34 ] [ 12 ]

其中 [34] 是低字节,存储在低地址处;[12] 是高字节,存储在高地址处。

2.小端数据收发

假设我们现在有一个UDP头的数据结构如下所示。

    //UDP协议头
    typedef struct
    {
        quint16 type;               //报文类型
        quint16 num;                //报文序号,取值范围为0~65535
        quint32 len;                //报文长度
        quint16 srcAddr;            //信源地址
        quint16 dstAddr;            //信宿地址
        quint8  year;               //发送时间  年份后两位   UTC时间
        quint8  month;
        quint8  day;
        quint8  hour;
        quint8  minute;
        quint8  second;
    }UdpHeader;

数据发送:组包。

QByteArray pack(const Protocol::UdpHeader &header)
{
    QByteArray byte;
    byte.append((char*)&(header.type),2);
    byte.append((char*)&(header.num),2);
    byte.append((char*)&(header.len),4);
    byte.append((char*)&(header.srcAddr),2);
    byte.append((char*)&(header.dstAddr),2);

    QString format = "yy-MM-dd-hh-mm-ss";
    QDateTime dateTime = QDateTime::currentDateTime();
    dateTime.setTimeSpec(Qt::LocalTime);

    QDateTime utcTime = dateTime.toUTC();

    QString strUtcTime = utcTime.toString(format);

    QStringList timeList = strUtcTime.split('-');

    quint8 year = timeList.at(0).toInt();
    quint8 month = timeList.at(1).toInt();
    quint8 day = timeList.at(2).toInt();
    quint8 hour = timeList.at(3).toInt();
    quint8 minute = timeList.at(4).toInt();
    quint8 sec = timeList.at(5).toInt();

    byte.append(year);
    byte.append(month);
    byte.append(day);
    byte.append(hour);
    byte.append(minute);
    byte.append(sec);

    return byte;
}

数据接收:拆包

void unPack(const QByteArray &byte, Protocol::UdpHeader &header)
{
    if(byte.size() != UDP_HEADER_LEN)
    {
        return;
    }

    memcpy(&header,byte.data(),sizeof(Protocol::UdpHeader));
}

3.大端数据收发

还是上面的头例子。
数据发送:组包。
使用QDataStream类作为辅助,设置setByteOrder为大端序列。

QByteArray packBigEndian(const Protocol::UdpHeader &header)
{
    QByteArray byte;
    QDataStream stream(&byte,QIODevice::WriteOnly);
    stream.setByteOrder(QDataStream::BigEndian);

    stream<<(header.type);
    stream<<(header.num);
    stream<<(header.len);
    stream<<(header.srcAddr);
    stream<<(header.dstAddr);

    QString format = "yy-MM-dd-hh-mm-ss";
    QDateTime dateTime = QDateTime::currentDateTime();
    dateTime.setTimeSpec(Qt::LocalTime);

    QDateTime utcTime = dateTime.toUTC();

    QString strUtcTime = utcTime.toString(format);

    QStringList timeList = strUtcTime.split('-');

    quint8 year = timeList.at(0).toInt();
    quint8 month = timeList.at(1).toInt();
    quint8 day = timeList.at(2).toInt();
    quint8 hour = timeList.at(3).toInt();
    quint8 minute = timeList.at(4).toInt();
    quint8 sec = timeList.at(5).toInt();

    stream<<year;
    stream<<month;
    stream<<day;
    stream<<hour;
    stream<<minute;
    stream<<sec;

    return byte;
}

数据接收:拆包。
对于多字节的数据,都需要单独使用qToBigEndian转换为大端。

void unPackBigEndian(const QByteArray &byte, Protocol::UdpHeader &header)
{
    if(byte.size() != UDP_HEADER_LEN)
    {
        return;
    }

    memcpy(&header,byte.data(),sizeof(Protocol::UdpHeader));
    header.type = qToBigEndian(header.type);
    header.num= qToBigEndian(header.num);
    header.len= qToBigEndian(header.len);
    header.srcAddr= qToBigEndian(header.srcAddr);
    header.dstAddr= qToBigEndian(header.dstAddr);
}

http://www.kler.cn/a/407508.html

相关文章:

  • 鸿蒙学习高效开发与测试-测试工具(5)
  • 微信小程序技术架构图
  • IDEA2023 SpringBoot整合MyBatis(三)
  • 文件管理 II(文件的物理结构、存储空间管理)
  • Kubernetes的pod控制器
  • SpringCloud Gateway转发请求到同一个服务的不同端口
  • ssm169基于Java的学习交流论坛+vue(论文+源码)_kaic
  • #渗透测试#红蓝攻防#HW#SRC漏洞挖掘01之静态页面渗透
  • 6G通信技术对比5G有哪些不同?
  • DAMODEL丹摩|丹摩智算平台:开启Llama3.1探索之旅
  • 网络爬虫——常见问题与调试技巧
  • 多目标粒子群优化(Multi-Objective Particle Swarm Optimization, MOPSO)算法
  • element-plus入门教程:安装
  • Cmakelist.txt之win-odbc-mysql
  • 如何通过OpenSSL基于根证书来签署客户端与服务器证书?
  • 【unity小技巧】Unity 和 C# 中使用多种方式进行不同的变量类型转换
  • 【爬虫】Firecrawl对京东热卖网信息爬取(仅供学习)
  • 动态规划算法--01背包问题详细讲解步骤
  • Oracle热备过程中对数据库崩溃的处理方法
  • Python爬虫能处理动态加载的内容吗?
  • C语言的文件函数
  • 如何在 Elasticsearch 中配置 SSL / TLS ?
  • win10局域网加密共享设置
  • 数据结构之——红黑树
  • Hive基础笔记
  • 【数据结构-队列】力扣232. 用栈实现队列