这次用一个更加复杂的数据包举例。
心跳报文结构如下:
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进制字符串转换为QByteArrayQByteArray 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进制字符串转换为QByteArrayQByteArray 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;}}// 将字典存入vectordataVector.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);
}