字节序即字节顺序,一般都是针对多字节数据类型而言。一般宽字节指int 或者double等非char类型。
分类:
1. 大端序。
2. 小端序。
3. 混合序。
大端序:
数值的高位放在内存地址的低位,数值的其他低位依次放在内存地址的后续(地址增加)位置上。
代表:power_pc
小端序:
与大端序相反,数值的低位放在内存的低位,数值的后续高位一次放在内存地址的后续(地址增加)位置上。
代表:X86
为了清晰,下面举个例子:
数值:0XABCDEF12 //32位
内存地址由低到高:0X01000001 0X010002 0X010003 0X010004
大端存储结果 :12 EF CD AB
小端存储结果 :AB CD EF 12
网络字节序:
当使用SOCKET对数据进行传输时,两端可能端序就不一样,当传输宽字节数据时,就可能会出现两端数据解析不一致的问题,所以就需要两边协调一种端序,这样两端才能识别数据。因此就需要使用网络字节序。
在send出去之前,先把需要发送的宽字节转换为网络字节序数据(内存块)。在receive之后,再将网络字节序转换为本地字节序,再使用。
网络字节序一般都使用大端序。伯克利socket api中有一组字节序转换函数,可以将16比特及32比特的宽字节进行转换, htonl/htons本地转网络字节序,ntonl/ntons网络字节序转本地字节序。
常见问题:
1. 对宽字节序做数据验证时,可能会出现异常,把宽字节直接当作多个char指针数据进行操作,由于大小端字节序的问题,取出来验证的数据完全相反。
解决方法:a.以宽字节作为一个整体进行处理及验证;
b.或者使用位运算(&&)来提取宽字节的每一个字节,重新排序后对提取到的字节进行统一处理。
2. socket传输数据异常。
解决方法:
a. Socket两端是否端序一致,端序不一致时,是否做过网络字节序转换,转换时,是否按照每32位与16位的数据类型进行的转换。转换的数值类型是否有非16位或者32位的数据。
b. 如果对于double或者其他的数据类型(非16或32位)可以直接将其转换为字符串,或者做一次序列化的操作,将其转换为与大小端无关的数据。在另一端做反序列化处理,还原数据。