这次用一个更加复杂的数据包举例。
心跳报文结构如下:
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 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);
}