场景:嵌入式设备中数据的交互的,比如串口,udp/tcp一般都是自定义的协议, 举个例子,如下协议,使用udpscoket进行数据的收发。
内容 | 值 | 解释 | |
STE | 2个字符 | 0x55 0x66 | 新数据开始 |
SYSID | 发送方ID | 1字节 | |
LEN | 两个字节 | Msg_type+payload的字节长度 | |
MSG_TYPE | 1个字节 | 消息类型 | |
PAYLOAD | 负载数据 |
一, 心跳包的发送。
假设心跳包的 MSG_TYPE 为01,负载数据为 00 88。发送方ID 也为88。
那完整的16进制 心跳包为 0x55 0x66 0x88 0x00 0x03 0x01 0x00 0x88
使用QT 封装
//心跳结构体
struct HeartbeatInfo
{
uint16_t sn{88};
};
QByteArray cmd;
//头
unsigned char head[2] = {0x55, 0x66};
for(int i=0;i<2;i++){
cmd.push_back(head[i]);
}
//sysid
uint8_t sysID{88};
cmd.append(QByteArray::fromHex(QString::number(sysID).toLatin1()));
//消息类型
uint8_t msgType=01;
//负载数据
uint16_t sn{88};
//长度
uint16_t len = sizeof(HeartbeatInfo)+1;
QDataStream baStream(&cmd,QIODevice::Append);
baStream<<len;
baStream<<msgType;
baStream<<sn;
//串口 或者socket 发送
mSocket->writeDatagram(cmd,QHostAddress::Broadcast,mPort)
二,心跳包的接收
QByteArray data;
//判断数据头 是否正确
if(data.at(0)!=0x55&&data.at(1)!=0x55){
return;
}
//消息类型
uint8_t msgType = data.at(5);
//Msg_type+payload的字节长度
uint16_t len = 0;
QByteArray lenData;
lenData = data.mid(4, 2);
len |= lenData.at(0) << 8 & 0xFF00;
len |= lenData.at(1) & 0x00FF;
//负载数据
QByteArray payloadData;
payloadData = data.mid(6, len-1);
//解析负载数据 需要大端转小端 qToBigEndian()
if(msgType ==01)
HeartbeatInfo *heartbeat = reinterpret_cast<HeartbeatInfo *>(payloadData.data());