如何用htons()、htonl()、ntohs()、ntohl()实现网络字节序转换?

摘要:前言 在计算机网络学到Socket编程的时候,自己在Linux下用C语言试验了一番,发现了这四个古怪的函数:htons()、htonl()、ntohs()、ntohl()。 查阅资料得知,这是涉及到网络字节序与主机字节序的转换。 字节序,顾
前言 在计算机网络学到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具体编程细节来理解。 参考资料 https://zhuanlan.zhihu.com/p/180556309