Welcome 微信登录

首页 / 数据库 / MySQL / socket编程:字节序

接触到socket编程,就一定会接触字节序转换。对于字符串来说,是没有字节序的差别的,就像我们写字,内存就像是纸,字符串就从左向右依次写:内存地址:00000000 00000001 00000002 00000003 ...内存数据:   "A"            "B"            "C"            "D"而任何cpu读取的时候,也都是从左向右依次读取。对于多字节数据(比如short、int、long...),不同字节序是有差别的。所有x86架构cpu(包括x64)都是用的小端字节序,网络字节序是大端序:int a = 0x01020304;内存地址:00000000 00000001 00000002 00000003 ...大端序a :    0x01        0x02        0x03        0x04            即cpu读出的数据从高向低位写入变量小端序a :    0x04        0x03        0x02        0x01            即cpu读出的数据从低向高位写入变量 如果我们写的程序不进行字节序转换会怎么样呢:int a = 0x01020304;在我们x86架构机器的内存里,它是这样写的0x04030201(注意,这是它在内存里的真实写法,当我们的程序以int型读取的时候才会转化成0x01020304),此时进行网络发送,send程序会以字节的方式(可以把它想象成字符串),一字节一字节的发送,到了网络上,它的顺序仍然是0x04030201(此时它的顺序已经错了)。当数据到达对端机器的时候,对端机器也是一字节一字节的收入内存,它的顺序仍然是0x04030201。如果对端仍是x86架构,那么数据读出来的时候它又被转化成了0x01020304,这看起来像是对的。但是如果对端是大端序的架构,那么它的int型数据就变成了0x04030201。字节序转换:Linux里提供了现成的函数:htonl, ntohl ...     这是一系列函数,却只提供了2字节和4字节的转换。判断字节序:int is_big_endian(void) {
    int test = 0x12345678;
    char *p = (char *)&p;    if(*p = 0x12)
        return 1;
    else
        return 0;
}函数虽然简陋,但是已经够用了。字节序转换宏,顺便将数字转换成数组:#define rhton16(h, n) {(n)[0]=((unsigned short)(h))>>8; (n)[1]=((unsigned short)(h))<<8>>8;}
#define rhton32(h, n) {(n)[0]=((unsigned int)(h))>>24; (n)[1]=((unsigned int)(h))<<8>>24; (n)[2]=((unsigned int)(h))<<16>>24; (n)[3]=((unsigned int)(h))<<24>>24;}
#define rhton64(h, n) {(n)[0]=((unsigned long)(h))>>56; (n)[1]=((unsigned long)(h))<<8>>56; (n)[2]=((unsigned long)(h))<<16>>56; (n)[3]=((unsigned long)(h))<<24>>56; (n)[4]=((unsigned long)(h))<<32>>56; (n)[5]=((unsigned long)(h))<<40>>56; (n)[6]=((unsigned long)(h))<<48>>56; (n)[7]=((unsigned long)(h))<<56>>56;}数组转换成数字:#define rntoh16(n) (((unsigned short)((n)[1])) | ((unsigned short)((n)[0])<<8))
#define rntoh32(n) (((unsigned int)((n)[3])) | ((unsigned int)((n)[2])<<8) | ((unsigned int)((n)[1])<<16) | ((unsigned int)((n)[0])<<24))
#define rntoh64(n) (((unsigned long)((n)[7])) | ((unsigned long)((n)[6])<<8) | ((unsigned long)((n)[5])<<16) | ((unsigned long)((n)[4])<<24) | ((unsigned long)((n)[3])<<32) | ((unsigned long)((n)[2])<<40) | ((unsigned long)((n)[1])<<48) | ((unsigned long)((n)[0])<<56))本文永久更新链接地址