共计 2278 个字符,预计需要花费 6 分钟才能阅读完成。
古代 CPU 一次至多能装载 4 字节 (32 位机), 即一个整数,这 4 个字节在内存中的排列程序将影响它的值。这就是字节序问题。字节序分为大端字节序(big endian) 和小端字节序(little endian)。
如上图,大端字节序是指数据的高位存在内存的低地址处,小端字节序是指数据的高位存在内存的高地址处。
古代 PC 大多采纳小端字节序。当格式化的数据须要在两台应用不同字节序的主机进行传递时,接收端会谬误的解决。解决的办法是: 发送端将发送的数据转换成大端字节序而后发送,接收端依据本人的字节序决定需不需要解决(小端转换,大端不解决)。
在做网络编程的时候,应用提供的库即可进行转换(linux 库,windows 下是一样的,头文件有所区别)
#include <netinet/in.h>
unsigned long int _htonl(unsigned long int hostlong);
unsigned short int _htons(unsigned short int hostshort);
unsigned long int _ntohl(unsigned long int netlong);
unsigned short int _ntohs(unsigned short int netshort);
如果平台没有提供这套,那么能够本人实现一下,原理很简略,就是调换下数据
#include <stdint.h>
#define BigLittleSwap16(v) ((0xFF00 & (uint16_t)(v)) >> 8 | (0x00FF & (uint16_t)(v)) << 8)
#define BigLittleSwap32(v) ((0xFF000000 & (uint32_t)(v)) >> 24 | (0x00FF0000 & (uint32_t)(v)) >> 8 | (0x0000FF00 & (uint32_t)(v)) << 8 | (0x000000FF & (uint32_t)(v)) << 24)
#define BigLittleSwap64(v) ((0xFF00000000000000 & (uint64_t)(v)) >> 56 |(0x00FF000000000000 & (uint64_t)(v)) >> 40 |(0x0000FF0000000000 & (uint64_t)(v) )>> 24 |(0x000000FF00000000 & (uint64_t)(v)) >> 8 |(0x00000000FF000000 & (uint64_t)(v)) << 8| (0x0000000000FF0000 & (uint64_t)(v)) << 24 | (0x000000000000FF00 & (uint64_t)(v) )<< 40 | (0x00000000000000FF & (uint64_t)(v) )<< 56 )
int isCPUBigEndian(){
union Data{
short val;
char byte;
} data;
data.val = 0x0102;
return (data.byte == 0x01);
}
unsigned long int _htonl(unsigned long int hostlong);
unsigned short int _htons(unsigned short int hostshort);
unsigned long int _ntohl(unsigned long int netlong);
unsigned short int _ntohs(unsigned short int netshort);
unsigned long int _htonl(unsigned long int hostlong){return isCPUBigEndian() ? hostlong : BigLittleSwap32(hostlong);
}
unsigned short int _htons(unsigned short int hostshort){return isCPUBigEndian() ? hostshort : BigLittleSwap16(hostshort);
}
unsigned long int _ntohl(unsigned long int netlong){return isCPUBigEndian() ? netlong : BigLittleSwap32(netlong);
}
unsigned short int _ntohs(unsigned short int netshort){return isCPUBigEndian() ? netshort : BigLittleSwap16(netshort);
}
测试:
#include <netinet/in.h>
#include <stdio.h>
int main(int argc,const char*argv[]){
long int v1 = 0x11223344;
short int v2 = 0x1122;
printf("the endian of system is:%s\n",isCPUBigEndian()?"Big Endian":"Little Endian");
printf("htonl:%x , %x , %x\n",v1,htonl(v1),_htonl(v1));
printf("htons:%x , %x , %x\n",v2,htons(v2),_htons(v2));
printf("ntohl:%x , %x , %x\n",v1,ntohl(v1),_ntohl(v1));
printf("ntohs:%x , %x , %x\n",v2,htons(v2),_htons(v2));
return 0;
}
在 linux 下的测试后果如下图
正文完