目录
1 网络字节序与地址变换
不同CPU,4字节整数型值“1”在内存空间中的保存方式是不同的。4字节整数型值“1”可用2进制表示如下:
00000000 00000000 00000000 00000001
而有些CPU以这种顺序保存到内存
00000001 00000000 00000000 00000000
在实际收发数据中,保存顺序的不同意味着对接收数据的解析顺序也不同。
1.1 字节序(Order)与网络字节序
CPU向内存保存数据的方式有2种,意味着CPU解析数据的方式也分为2种。
- 大端序(Big Endian):高位字节存放到低位地址
- 小端序(Little Endian):高位字节存放到高位地址
大端序的CPU保存方式如下图所示:
从上图不难看出,整数0x12345678,0x12是最高位字节,0x78是最低位字节。因此大端序中最先保存的最高位字节是0x12(最高位字节0x12存放到低位地址)。
小端序保存方式如图所示:
最先保存的是低位字节0x78。从上可以分析得出,每种CPU的数据保存方式均不同。因此代表CPU数据保存方式的主机字节序(Host Byte Order)在不同CPU中也各不相同。
当两台字节序不同(CPU保存方式)的计算机间数据传递过程中,可能会出现数据读错的情况,见下列情景:
0x12和0x34构成的大端序系统值与0x34和0x12构成的小端序系统值相同,大端序系统传输数据01234时未考虑字节序的问题,而以0x12、0x34的顺序发送。
然而接收端以小端序方式保存数据,因此小端序接收的数据变成0x3412,而非0x1234。所以在通过网络传输数据时我们需要约定统一方式,并把这种约定成为网络字节序(Network Byte Order)。
无论大端序CPU还是小端序CPU,统一在传输时使用大端序,也就是把数据数组转换成为大端序格式再进行网络传输。因此所有计算机接收数据时应识别该数据时网络字节序格式,小端序系统传输数据时应转化为大端序排列方式。
1.2 字节序转换(Endian Conversions)
需要了解的帮助转换字节序的函数:
- unsigned short htons (unsigned short);
- unsigned short ntohs (unsigned short);
- unsigned long htonl (unsigned long);
- unsigned long ntohl (unsigned long);
通过函数名应能掌握其功能,需了解以下细节
- htons中的h代表是主机(Host)字节序。
- htons中的n代表网络(network)字节序。
例如:
- 把short型数据从主机字节序转化为网络字节序,我们可以使用htos(short)
- 把short型数据从网络字节序转化为主机字节序,我们可以使用ntos(short)
下列代码为函数的调用过程:
#include <stdio.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
unsigned short host_port=0x1234;
unsigned short net_port;
unsigned long host_addr=0x12345678;
unsigned long net_addr;
net_port=htons(host_port);
net_addr=htonl(host_addr);
printf("Host ordered port: %#x \n", host_port);
printf("Network ordered port: %#x \n", net_port);
printf("Host ordered address: %#lx \n", host_addr);
printf("Network ordered address: %#lx \n", net_addr);
return 0;
}
运行结果: