系统1:ThinkPad T570、Windows10、QT5.12.2(Qt Creater 4.8.2)
在与其他设备进行UDP通信时,我一般会定义通信协议包结构,如下图所示是一个简单的例子:
,然后在程序中我会定义一个结构体,如下所示:
struct PACKET_PC1_PC2
{
quint32 m_nFrameHead;//0xFFAA低位在前,高位在后
quint32 m_nUtcTime[2];//时戳,UTC相对时间,以秒为单位,以1970年1月1日0时0分0秒为基准。第一个字段表示整秒数,第二个字段表示为毫秒数
qint16 m_nDataTypeID;//0:默认值 1:config文件数据 2:ini文件数据 3:csv数据
quint32 m_nPacketID;//发送的包序号
char m_cReserved[490];
quint32 m_nFrameEnd;//0xFFFF低位在前,高位在后
};
然后定义一个结构体对象,并对其赋值
PACKET_PC1_PC2 packetPc1_Pc2;
//...... 对packetPc1_Pc2进行赋值
然后将packetPc1_Pc2通过socket发送出去
QByteArray baData;
baData.resize(sizeof(PACKET_PC1_PC2));
char* ptr_ctemp = baData.data();
memcpy(ptr_ctemp,&packetPc1_Pc2,sizeof(PACKET_PC1_PC2));
qint64 nSendLen = m_SocketSendCSV->writeDatagram(baData,QHostAddress(m_strRemoteIP),m_nRemotePort);
接下来问题来了,对方收到包发现变量m_nPpakcetID的值死活都不对,然后我用wireshark抓包,研究了半天才发现抓到的包里面的变量m_nDataTypeID和变量m_nPpakcetID所在的字节之间多了2个字节,且多出来的2个字节的值都为0,然后我就断定肯定是字节对齐的问题!系统默认是4字节对齐的,就是说变量m_nDataTypeID占用内存由2个字节编程了4个字节
每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。
n 字节的对齐方式对结构的存储的特殊处理确实提高 CPU 存储变量的速度,但是有时候也带来 了一些麻烦,就像我上面描述的问题那样。
解决方法:
在结构体前后加上如下代码进行字节对齐:
#pragma pack(push) //保存对齐状态
#pragma pack(1)//设定为1字节对齐
struct PACKET_PC1_PC2
{
quint32 m_nFrameHead;//0xFFAA低位在前,高位在后
quint32 m_nUtcTime[2];//时戳,UTC相对时间,以秒为单位,以1970年1月1日0时0分0秒为基准。第一个字段表示整秒数,第二个字段表示为毫秒数
qint16 m_nDataTypeID;//0:默认值 1:config文件数据 2:ini文件数据 3:csv数据
quint32 m_nPacketID;//发送的包序号
char m_cReserved[490];
quint32 m_nFrameEnd;//0xFFFF低位在前,高位在后
};
#pragma pack(pop)//恢复对齐状态