Socket编程: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

posted @ 2023-09-17 16:29  江水为竭  阅读(223)  评论(0编辑  收藏  举报