Qt中对Udp数据打包发送和接收(续)

news/2024/5/18 12:07:33 标签: qt, udp, 开发语言

这次用一个更加复杂的数据包举例。

心跳报文结构如下:

struct HeartbeatPacket {
    quint16 protocolId;
    quint16 version;
    quint16 totalLength;
    quint16 reserve;
    QByteArray senderAddress;
    QByteArray receiverAddress;
    quint8 sequenceNumber;
    quint8 acknowledgementNumber;
    quint8 messageFlag;
    quint8 unitCount;
    quint8 unitNumber;
    quint8 unitId;
    QByteArray unitLength;
    QByteArray timestamp;
    QByteArray deviceId;

    QByteArray toByteArray();


};

代码如下:

QByteArray HeartbeatPacket::toByteArray() {
    QByteArray byteArray;
    QDataStream stream(&byteArray, QIODevice::WriteOnly);

    // 注意:此处可能需要考虑字节序问题
    stream << protocolId;
    stream << version;
    stream << totalLength;
    stream << reserve;
    stream.writeRawData(senderAddress.constData(), senderAddress.size());
    stream.writeRawData(receiverAddress.constData(), receiverAddress.size());
    stream << sequenceNumber;
    stream << acknowledgementNumber;
    stream << messageFlag;
    stream << unitCount;
    stream << unitNumber;
    stream << unitId;
    stream.writeRawData(unitLength.constData(), unitLength.size());
    stream.writeRawData(timestamp.constData(), timestamp.size());
    stream.writeRawData(deviceId.constData(), deviceId.size());

    return byteArray;
}

void MainWindow::sendHeartbeat(const QHostAddress &address, quint16 port)
{
    QByteArray packetData = heartbeatPacket.toByteArray();
    udpSocket.writeDatagram(packetData, address, port);
}

void MainWindow::convertVectorToHeartbeatPacket()
{
    if (dataVector.size() < 13) {
        qDebug() << "vector size too short.";
        return;
    }

    bool reverseBytes = false;  // 默认字节序为低字节在前

    auto reverseIter = dataVector[3].find("name");
    if (reverseIter != dataVector[3].end() && reverseIter->second == "reverse") {
        auto valueIter = dataVector[3].find("value");
        if (valueIter != dataVector[3].end()) {
            QString reverseValue = valueIter->second.toLower();
            if (reverseValue == "True") {
                reverseBytes = true;
            }
        }
    }

    heartbeatPacket.protocolId = dataVector[0].at("value").toUShort();
    heartbeatPacket.version = dataVector[1].at("value").toUShort();
    heartbeatPacket.totalLength = dataVector[2].at("value").toUShort();
    heartbeatPacket.reserve = dataVector[3].at("value").toUShort();

    // 设置senderAddress和receiverAddress,需要将16进制字符串转换为QByteArray,并根据reverseBytes确定字节序
    QByteArray senderAddressHex = dataVector[4].at("value").toUtf8();
    QByteArray receiverAddressHex = dataVector[5].at("value").toUtf8();
    QByteArray senderAddressBytes;
    QByteArray receiverAddressBytes;

    if (reverseBytes) {
        // 高字节在前的字节序
        for (int i = senderAddressHex.size() - 2; i >= 0; i -= 2) {
            senderAddressBytes.append(senderAddressHex.mid(i, 2).toInt(nullptr, 16));
            receiverAddressBytes.append(receiverAddressHex.mid(i, 2).toInt(nullptr, 16));
        }
    } else {
        // 低字节在前的字节序
        for (int i = 0; i < senderAddressHex.size(); i += 2) {
            senderAddressBytes.append(senderAddressHex.mid(i, 2).toInt(nullptr, 16));
            receiverAddressBytes.append(receiverAddressHex.mid(i, 2).toInt(nullptr, 16));
        }
    }

    heartbeatPacket.senderAddress = senderAddressBytes;
    heartbeatPacket.receiverAddress = receiverAddressBytes;

    heartbeatPacket.sequenceNumber = dataVector[6].at("value").toShort();
    heartbeatPacket.acknowledgementNumber = dataVector[7].at("value").toShort();
    heartbeatPacket.messageFlag = dataVector[8].at("value").toShort();
    heartbeatPacket.unitCount = dataVector[9].at("value").toShort();
    heartbeatPacket.unitNumber = dataVector[10].at("value").toShort();
    heartbeatPacket.unitId = dataVector[11].at("value").toShort();

    QByteArray unitLengthHex = dataVector[12].at("value").toUtf8();
    QByteArray unitLengthBytes;
    // 低字节在前的字节序
    for (int i = 0; i < unitLengthHex.size(); i += 2) {
        unitLengthBytes.append(unitLengthHex.mid(i, 2).toInt(nullptr, 16));
    }
//    // 高字节在前的字节序
//    for (int i = unitLengthHex.size() - 2; i >= 0; i -= 2) {
//        unitLengthBytes.append(unitLengthHex.mid(i, 2).toInt(nullptr, 16));
//    }

    heartbeatPacket.unitLength = unitLengthBytes;

    // 设置timestamp,需要将16进制字符串转换为QByteArray
    QByteArray timestampHex = dataVector[13].at("value").toUtf8();
    QByteArray timestampBytes;

    if (reverseBytes) {
        // 高字节在前的字节序
        for (int i = timestampHex.size() - 2; i >= 0; i -= 2) {
            timestampBytes.append(timestampHex.mid(i, 2).toInt(nullptr, 16));
        }
    } else {
        // 低字节在前的字节序
        for (int i = 0; i < timestampHex.size(); i += 2) {
            timestampBytes.append(timestampHex.mid(i, 2).toInt(nullptr, 16));
        }
    }

    heartbeatPacket.timestamp = timestampBytes;

    // 设置deviceId,需要将16进制字符串转换为QByteArray
    QByteArray deviceIdHex = dataVector[14].at("value").toUtf8();
    QByteArray deviceIdBytes;

    if (reverseBytes) {
        // 高字节在前的字节序
        for (int i = deviceIdHex.size() - 2; i >= 0; i -= 2) {
            deviceIdBytes.append(deviceIdHex.mid(i, 2).toInt(nullptr, 16));
        }
    } else {
        // 低字节在前的字节序
        for (int i = 0; i < deviceIdHex.size(); i += 2) {
            deviceIdBytes.append(deviceIdHex.mid(i, 2).toInt(nullptr, 16));
        }
    }

    heartbeatPacket.deviceId = deviceIdBytes;
}

bool MainWindow::LoadXmlContent(QString FileName)
{

    QString FilePath = m_selectedFolderPath + "/" + FileName + ".xml";

    QFile file(FilePath); // 替换为您实际的文件路径
        if (!file.open(QIODevice::ReadOnly)) {
            qDebug() << "Can not open file。";
            return false;
        }

        QDomDocument document;
        if (!document.setContent(&file)) {
            qDebug() << "无法将文件解析为DOM树。";
            file.close();
            return false;
        }
        file.close();

        dataVector.clear();
        QDomElement root = document.firstChildElement(); // 获取根元素

            // 遍历所有子元素
            QDomNodeList elements = root.childNodes();
//            for (int i = 0; i < elements.count(); i++) {
//                    QDomNode elementNode = elements.at(i);
//                    // 检查节点是否为元素。
//                    if (elementNode.isElement()) {
//                        QDomElement element = elementNode.toElement();

//                        QDomNodeList childNodes = element.childNodes();
//                        for (int j = 0; j < childNodes.count(); j++) {
//                            QDomNode childNode = childNodes.at(j);
//                            if (childNode.isElement()) {
//                                QDomElement childElement = childNode.toElement();
//                                qDebug() << childElement.nodeName() << ":" << childElement.text();
//                            }
//                        }
//                    }
//            }
            for (int i = 0; i < elements.count(); i++) {
                    QDomNode elementNode = elements.at(i);
                    // 检查节点是否为元素。
                    if (elementNode.isElement()) {
                        QDomElement element = elementNode.toElement();

                        QDomNodeList childNodes = element.childNodes();

                        // 创建一个字典来存储键值对
                        std::map<QString, QString> dataMap;

                        for (int j = 0; j < childNodes.count(); j++) {
                            QDomNode childNode = childNodes.at(j);
                            if (childNode.isElement()) {
                                QDomElement childElement = childNode.toElement();
//                                QString key = childElement.nodeName();
                                QString key = childElement.nodeName();
                                // 将键的第一个字母转换为小写
                                if (!key.isEmpty()) {
                                    key[0] = key[0].toLower();
                                }
                                QString value = childElement.text();
                                // 将键值对存入字典
                                dataMap[key] = value;
                            }
                        }

                        // 将字典存入vector
                        dataVector.push_back(dataMap);
                    }
                }

                // 打印存储的数据
                for (const auto& data : dataVector) {
                    for (const auto& pair : data) {
                        qDebug() << pair.first << ":" << pair.second;
                    }
                    qDebug() << "-------------------";
                }
}

void MainWindow::onSendButtonClicked()
{
    LoadXmlContent("心跳报文");
    convertVectorToHeartbeatPacket();
    // 发送心跳报文到广播地址
    sendHeartbeat(QHostAddress::Broadcast, 12345);
}


http://www.niftyadmin.cn/n/5233166.html

相关文章

POSTGRESQL中如何利用SQL语句快速的进行同环比?

1. 引言 在数据驱动的时代&#xff0c;了解销售、收入或任何业务指标的同比和环比情况对企业决策至关重要。本文将深入介绍如何利用 PostgreSQL 和 SQL 语句快速、准确地进行这两种重要分析。 2. 数据准备 为了演示&#xff0c;假设我们有一张 sales 表&#xff0c;存储了销…

信息学奥赛一本通1187:统计字符数

1187&#xff1a;统计字符数 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 28160 通过数: 16067 【题目描述】 给定一个由a-z这26个字符组成的字符串&#xff0c;统计其中哪个字符出现的次数最多。 【输入】 输入包含一行&#xff0c;一个字符串&#xff0c;长度…

四川成都数字创新大赛-2数据交易平台带给智慧农业项目的优势

目录 产业互联网是什么 数据资产定义 数据交易平台带给智慧农业项目的优势

【超全】React学习笔记 中:进阶语法与原理机制

React学习笔记 React系列笔记学习 上篇笔记地址&#xff1a;【超全】React学习笔记 上&#xff1a;基础使用与脚手架 下篇笔记地址&#xff1a;【超全】React学习笔记 下&#xff1a;路由与Redux状态管理 React进阶组件概念与使用 1. React 组件进阶导读 在掌握了 React 的基…

【同济大学主办】第七届先进算法与控制工程国际学术会议(ICAACE 2024)

第七届先进算法与控制工程国际学术会议&#xff08;ICAACE 2024&#xff09; 2024 7th International Conference on Advanced Algorithms and Control Engineering 第七届先进算法与控制工程国际学术会议&#xff08;ICAACE 2024&#xff09;定于2024年1月26-28日在中国上…

Python+Requests对图片验证码的处理

Requests对图片验证码的处理 在web端的登录接口经常会有图片验证码的输入&#xff0c;而且每次登录时图片验证码都是随机的&#xff1b;当通过request做接口登录的时候要对图片验证码进行识别出图片中的字段&#xff0c;然后再登录接口中使用&#xff1b; 通过request对图片验…

8.C转python

1.在文件查找中,文件夹才是目录 2.使用pip: python搞了一个网站pypi,把各种的第三方库给收集起来了 使用pip工具就可以直接从pypi里下载你想要的第三方库了 可以直接使用pip工具搜 安装完成后,即可使用import导入相关模块即可进行使用 往后运用pip中的第三方库应该都是在…

mysql8.0 提取json数据转为行

仅适用于mysql8.0&#xff0c;之前的版本不支持JSON_TABLE函数 数据结构: idnamejsonarr1张三[{"daystr": "2023-12-01","score": "53"},{"daystr": "2023-12-02","score": "78"}]2李四[{&q…