网络字节序: MSB 高字节前存法 Most Significant Bit (Big Edian)
主机字节序: LSB 低字节前存法 Lest Significant Bit (Little Edian)
因为现行的计算机都是以八位一个字节为存储单位,那么一个16位的整数,也就是C语言中的short,在内存中可能有两种存储顺序big-endian和litte-endian。考虑一个short整数0x3132(0x32是低位,0x31是高位),把它赋值给一个short变量,那么它在内存中的存储可能有如下两种情况:
可以做个实验
在Windows上下如下程序
#include <stdio.h>
#include <assert.h>
int main(void)
{
short test;
FILE* fp;
test = 0x3132; /**//* (31ASIIC码的'1', 32ASIIC码的'2') */
if ((fp = fopen("c:\\test.txt", "wb")) == NULL)
assert(0);
fwrite(&test, sizeof(short), 1, fp);
fclose(fp);
return 0;
}
然后在C盘下打开test.txt文件,可以看见内容是21,而test等于0x3132,可以明显的看出来x86的字节顺序是低位在前。如果我们把这段同样的代码放到(big-endian)的机器上执行,那么打出来的文件就是12。这在本机中使用是没有问题的。但当你把这个文件从一个big-endian机器复制到一个little-endian机器上时就出现问题了。
如上述例子,我们在big-endian的机器上创建了这个test文件,把其复制到little-endian的机器上再用fread读到一个short里面,我们得到的就不再是0x3132而是0x3231了,这样读到的数据就是错误的,所以在两个字节顺序不一样的机器上传输数据时需要特别小心字节顺序,理解了字节顺序在可以帮助我们写出移植行更高的代码。
正因为有字节顺序的差别,所以在网络传输的时候定义了所有字节顺序相关的数据都使用big-endian,BSD的代码中定义了四个宏来理:
#define ntohs(n) //网络字节顺序到主机字节顺序 n代表net, h代表host, s代表short
#define htons(n) //主机字节顺序到网络字节顺序 n代表net, h代表host, s代表short
#define ntohl(n) //网络字节顺序到主机字节顺序 n代表net, h代表host, s代表long
#define htonl(n) //主机字节顺序到网络字节顺序 n代表net, h代表host, s代表long