利用Qt实现网络数据报文大小端数据的收发
1.大小端数据简介
大小端(Endianness)是计算机体系结构的一个术语,它描述了多字节数据在内存中的存储顺序。以下是大小端的定义和它们的特点:
大端(Big-Endian)
在大端模式中,一个字的最高有效字节(MSB,即最左边的那位)存储在最低的内存地址处,而最低有效字节(LSB,即最右边的那位)存储在最高的内存地址处。
例如,假设有一个16位的数字 0x1234,其在内存中的存储顺序如下:
地址增加方向 -->
[ 12 ] [ 34 ]
其中 [12] 是高字节,存储在低地址处;[34] 是低字节,存储在高地址处。
小端(Little-Endian)
在小端模式中,情况正好相反:一个字的最低有效字节存储在最低的内存地址处,而最高有效字节存储在最高的内存地址处。
继续上面的例子,16位的数字 0x1234 在小端模式下的存储顺序如下:
地址增加方向 -->
[ 34 ] [ 12 ]
其中 [34] 是低字节,存储在低地址处;[12] 是高字节,存储在高地址处。
2.小端数据收发
假设我们现在有一个UDP头的数据结构如下所示。
//UDP协议头 typedef struct { quint16 type; //报文类型 quint16 num; //报文序号,取值范围为0~65535 quint32 len; //报文长度 quint16 srcAddr; //信源地址 quint16 dstAddr; //信宿地址 quint8 year; //发送时间 年份后两位 UTC时间 quint8 month; quint8 day; quint8 hour; quint8 minute; quint8 second; }UdpHeader;
数据发送:组包。
QByteArray pack(const Protocol::UdpHeader &header) { QByteArray byte; byte.append((char*)&(header.type),2); byte.append((char*)&(header.num),2); byte.append((char*)&(header.len),4); byte.append((char*)&(header.srcAddr),2); byte.append((char*)&(header.dstAddr),2); QString format = "yy-MM-dd-hh-mm-ss"; QDateTime dateTime = QDateTime::currentDateTime(); dateTime.setTimeSpec(Qt::LocalTime); QDateTime utcTime = dateTime.toUTC(); QString strUtcTime = utcTime.toString(format); QStringList timeList = strUtcTime.split('-'); quint8 year = timeList.at(0).toInt(); quint8 month = timeList.at(1).toInt(); quint8 day = timeList.at(2).toInt(); quint8 hour = timeList.at(3).toInt(); quint8 minute = timeList.at(4).toInt(); quint8 sec = timeList.at(5).toInt(); byte.append(year); byte.append(month); byte.append(day); byte.append(hour); byte.append(minute); byte.append(sec); return byte; }
数据接收:拆包
void unPack(const QByteArray &byte, Protocol::UdpHeader &header) { if(byte.size() != UDP_HEADER_LEN) { return; } memcpy(&header,byte.data(),sizeof(Protocol::UdpHeader)); }
3.大端数据收发
还是上面的头例子。
数据发送:组包
使用QDataStream类作为辅助,设置setByteOrder为大端序列。
QByteArray packBigEndian(const Protocol::UdpHeader &header) { QByteArray byte; QDataStream stream(&byte,QIODevice::WriteOnly); stream.setByteOrder(QDataStream::BigEndian); stream<<(header.type); stream<<(header.num); stream<<(header.len); stream<<(header.srcAddr); stream<<(header.dstAddr); QString format = "yy-MM-dd-hh-mm-ss"; QDateTime dateTime = QDateTime::currentDateTime(); dateTime.setTimeSpec(Qt::LocalTime); QDateTime utcTime = dateTime.toUTC(); QString strUtcTime = utcTime.toString(format); QStringList timeList = strUtcTime.split('-'); quint8 year = timeList.at(0).toInt(); quint8 month = timeList.at(1).toInt(); quint8 day = timeList.at(2).toInt(); quint8 hour = timeList.at(3).toInt(); quint8 minute = timeList.at(4).toInt(); quint8 sec = timeList.at(5).toInt(); stream<<year; stream<<month; stream<<day; stream<<hour; stream<<minute; stream<<sec; return byte; }
数据接收:拆包
对于多字节的数据,都需要单独使用qToBigEndian转换为大端。
void unPackBigEndian(const QByteArray &byte, Protocol::UdpHeader &header) { if(byte.size() != UDP_HEADER_LEN) { return; } memcpy(&header,byte.data(),sizeof(Protocol::UdpHeader)); header.type = qToBigEndian(header.type); header.num= qToBigEndian(header.num); header.len= qToBigEndian(header.len); header.srcAddr= qToBigEndian(header.srcAddr); header.dstAddr= qToBigEndian(header.dstAddr); }
到此这篇关于利用Qt实现网络数据报文大小端数据的收发的文章就介绍到这了,更多相关Qt大小端数据收发内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
最新评论