简单demo:
发送端:
cpp
#include <QUdpSocket>
#include <QtEndian>
#pragma pack(1)
struct Test
{
unsigned char t1:1;
unsigned char t2:2;
unsigned char t3:3;
unsigned char t4:2;
quint8 a = 1;
quint16 b = 2;
quint16 c = 3;
//double b = 2;
quint8 d = 4;
quint8 e = 1;
};
#pragma pack(pop)
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QByteArray temp_byte_array;
Test test;
test.b = qToBigEndian(test.b);
test.c = qToBigEndian(test.c);
test.b = qToBigEndian(test.b);
test.t1 = 0x1;
test.t2 = 0x2;
test.t3 = 0x3;
test.t4 = 0x2;
QUdpSocket *m_pUdpSocket = new QUdpSocket();
m_pUdpSocket->bind(QHostAddress("127.0.0.1"),8002);
QByteArray frame = QByteArray((char *)&test, sizeof(Test));
m_pUdpSocket->writeDatagram(frame, QHostAddress("127.0.0.1"), 8001);
return 0;
}
接收:
cpp
#include <QUdpSocket>
#include <QtEndian>
#pragma pack(1)
struct Test
{
unsigned char t1:1;
unsigned char t2:2;
unsigned char t3:3;
unsigned char t4:2;
quint8 a = 0x1;
quint16 b = 0x2;
quint16 c = 0x3;
//double b = 2;
quint8 d = 0x4;
quint8 e = 0x1;
};
#pragma pack(pop)
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QUdpSocket *m_pUdpSocket = new QUdpSocket();
m_pUdpSocket->bind(QHostAddress("127.0.0.1"),8001);
QObject::connect(m_pUdpSocket,&QUdpSocket::readyRead,[=](){
QByteArray frame;
frame.resize(m_pUdpSocket->pendingDatagramSize());
// 接收数据报,将其存放到datagram中
m_pUdpSocket->readDatagram(frame.data(), frame.size());
struct Test *pFrame = (struct Test *)frame.data();
qDebug()<<"a:"<<pFrame->a;
qDebug()<<"b:"<<pFrame->b;
qDebug()<<"c:"<<pFrame->c;
qDebug()<<"d:"<<pFrame->d;
qDebug()<<"*****************";
});
return app.exec();
}
有帧头帧尾:
发送:
cpp
#include <QUdpSocket>
#include <QtEndian>
// 以1字节对齐:
#pragma pack(1)
struct Test
{
// 帧头 0xabcd
unsigned short dataHead = 0xabcd;
// 小于1字节:
unsigned char t1:1;
unsigned char t2:2;
unsigned char t3:3;
unsigned char t4:2;
// 小于或者大于1字节
quint8 a = 0x1;
quint16 b = 0x2;
quint16 c = 0x3;
quint8 d = 0x4;
quint8 e = 0x1;
// 包尾 dcba
unsigned short dataTail = 0xdcba;
};
#pragma pack(pop)
int main(int argc, char *argv[])
{
QByteArray temp_byte_array;
Test test;
//test.b = qToBigEndian(test.b);
//test.c = qToBigEndian(test.c);
test.t1 = 0x1;
test.t2 = 0x2;
test.t3 = 0x3;
test.t4 = 0x2;
QUdpSocket *m_pUdpSocket = new QUdpSocket();
m_pUdpSocket->bind(QHostAddress("127.0.0.1"),8002);
QByteArray frame = QByteArray((char *)&test, sizeof(Test));
m_pUdpSocket->writeDatagram(frame, QHostAddress("127.0.0.1"), 8001);
}
接受:
cpp
#include <QUdpSocket>
#include <QtEndian>
// 以1字节对齐:
#pragma pack(1)
struct Test
{
// 帧头 0xabcd
unsigned short dataHead = 0xabcd;
// 小于1字节:
unsigned char t1:1;
unsigned char t2:2;
unsigned char t3:3;
unsigned char t4:2;
// 小于或者大于1字节
quint8 a = 0x1;
quint16 b = 0x2;
quint16 c = 0x3;
quint8 d = 0x4;
quint8 e = 0x1;
// 包尾 dcba
unsigned short dataTail = 0xdcba;
};
#pragma pack(pop)
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QUdpSocket *m_pUdpSocket = new QUdpSocket();
m_pUdpSocket->bind(QHostAddress("127.0.0.1"),8001);
QObject::connect(m_pUdpSocket,&QUdpSocket::readyRead,[=](){
QByteArray frame;
frame.resize(m_pUdpSocket->pendingDatagramSize());
// 接收数据报,将其存放到datagram中
m_pUdpSocket->readDatagram(frame.data(), frame.size());
struct Test *pFrame = (struct Test *)frame.data();
if(pFrame->dataHead == 0xabcd && pFrame->dataTail == 0xdcba)
{
qDebug()<<"接收到信息*********";
qDebug()<<"a:"<<pFrame->a;
qDebug()<<"b:"<<pFrame->b;
qDebug()<<"c:"<<pFrame->c;
qDebug()<<"d:"<<pFrame->d;
qDebug()<<"*****************";
}
});
return app.exec();
}
会发现,如果不是这个帧头和帧尾,就会出问题,只有帧头帧尾正确,才可以正常解析。
注意事项:
-
结构体前后一定要加1字节对齐,否则可能会多出很多字节,比如你们可以自己尝试不加一字节对齐,然后加入double会增加多少的字节。
-
接收的时候,不要使用readall() 。
-
测试的时候,发送不要使用串口调试助手等工具,哪些会出问题。
-
大小端:很多系统默认小端,如果需要转为大端发送数据,大于1字节的数据,需要使用qToBigEndian()来转换。