前言
在计算机网络学到Socket编程的时候,自己在Linux下用C语言试验了一番,发现了这四个古怪的函数:htons()
、htonl()
、ntohs()
、ntohl()
。
查阅资料得知,这是涉及到网络字节序与主机字节序的转换。
字节序,顾名思义字节的顺序,就是大于一个字节类型的数据在内存中的存放顺序。
主机字节序
主机字节序就是我们平常说的大端和小端模式。
对于不同的ISA,不同的CPU,不同的操作系统,有不同的字节序类型。
可以看我之前的博客,了解大小端的区别。
标准的Big-Endian和Little-Endian的定义如下:
- Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
- Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
而为什么主机序会有大小端之分呢?
大端序是人类处理数字的自然方式,而小端序对于逻辑电路来说更高效。
网络字节序
网络字节序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。
网络字节序采用big endian排序方式。
所以,在将一个地址绑定到Socket的时候,请先将主机字节序转换成为网络字节序,而不要假定主机字节序跟网络字节序一样使用的是Big-Endian。(我们常用的x86系列的PC大多都是小端的)。
头文件
这四个函数都需要一个头文件:
#include <arpa/inet.h>
函数
所以在实际的Socket编程中,我们需要一下函数,对 IP地址 和 端口号 等操作数进行转换。方便我们传输或者使用(打印出)。
//主机字节序转换为网络字节序
uint32_t htonl (uint32_t hostlong);
uint16_t htons (uint16_t hostshort);
// htons: host to network short
// htonl: host to network long
//网络字节序转换为主机字节序
uint32_t ntohl (uint32_t netlong);
uint16_t ntohs (uint16_t netshort);
//ntohs: network to host short
//ntohl: network to host long
//h: host n: network s: short l: long
//short: 16位 long: 32位
数据类型
typedef __u16 uint16_t;
typedef __u32 uint32_t;
输出方式
数据类型 | 输出方式 |
---|---|
u16 | %d 或 %hu |
u32 | %u |
例子
具体例子需要结合Socket具体编程细节来理解。