socket编程“网络字节顺序”和“主机字节顺序”
1.大小端模式
在socket编程前,有必要知道大小端模式。大小端模式是指计算机内存中数据存放的模式,由CPU决定,与操作系统无关。大端模式(Big-endian,是指数据的高字节保存在内存的低地址中,数据的低字节保存在内存的高地址中,这种存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;与我们的阅读习惯一致。小端模式(Little-endian),是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。
大端模式CPU代表是IBM Power PC,小端模式CPU代表是Intel X86、ARM。
1.1 大小的模式存储内容
以0x12345678数据为例,两种模式在内存中的存储情况。
内存地址 | 小端模式存储内容 | 大端模式存储内容 |
---|---|---|
0x0000 | 0x78 | 0x12 |
0x0001 | 0x56 | 0x34 |
0x0002 | 0x34 | 0x56 |
0x0003 | 0x12 | 0x78 |
1.2 大小端CPU判断
可以通过执行一段程序来判断一个CPU的是大端还是小端模式。利用C语言共用体(联合体)中的几种不同类型的变量存放在同一段内存单元中的特点,可以用联合体快速实现判断大小端模式。
void bl_checkt(void)
{
union
{
int a;
char b;
}bl;
bl.a=0x01;
if (bl.b==0x01)
printf("Little endian");
else
printf("Big endian");
}
1.3 大小端转换
#define BL16(x) ((((x) & 0x00ffUL) << 8) | (((x) & 0xff00UL) >> 8))
#define BL32(x) ((((x) & 0x000000ffUL) << 24) | \
(((x) & 0x0000ff00UL) << 8) | \
(((x) & 0x00ff0000UL) >> 8) | \
(((x) & 0xff000000UL) >> 24))
2.网络字节顺序和主机字节顺序
在socket网络编程中,有两个基本是术语是必须掌握的,网络字节顺序(NBO,Network Byte Order)和主机字节顺序(HBO,Host Network Order)。
网络字节顺序,NBO是网络数据在传输中的规定的数据格式,从高到低位顺序存储,即低字节存储在高地址,高字节存储在低地址;即“大端模式”。网络字节顺序可以避免不同主机字节顺序的差异。
主机字节顺序,HBO则与机器CPU相关,数据的存储顺序由CPU决定。
3.常用转换函数
socket编程中经常会用到4个网络字节顺序与本地字节顺序之间的转换函数:htons()、ntohl()、 ntohs()、htons()。
htonl()--"Host to Network Long" 长整型数据主机字节顺序转网络字节顺序
ntohl()--"Network to Host Long" 长整型数据网络字节顺序转主机字节顺序
htons()--"Host to Network Short" 短整型数据主机字节顺序转网络字节顺序
ntohs()--"Network to Host Short" 短整型数据网络字节顺序转主机字节顺序
3.1 函数实现原型
函数实现,即为文章开头的大小端转换。
#define htons(x) (u16_t)BL16(x)
#define ntohs(x) (u16_t)BL16(x)
#define htonl(x) (u32_t)BL32(x)
#define ntohl(x) (u32_t)BL32(x)