htonl() htons() ntohl() ntohs()及inet_ntoa() inet_addr()的用法
一、网络字节序和主机字节序
注:其中的h表示“host”,n表示“net”,l表示“long”,s表示“short”,a表示“ascii”,addr表示“in_addr结构体”
这些函数都与网络字节序和主机字节序列的转换,首先介绍一下网络字节序和主机字节序列及两者之间的转换关系。
网络字节顺序NBO(Network Byte Order):
按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题。
主机字节顺序(HBO,Host Byte Order):
不同的机器HBO不相同,与CPU设计有关,数据的顺序是由cpu决定的,而与操作系统无关。
如 Intel x86结构下,short型数0x1234表示为34 12, int型数0x12345678表示为78 56 34 12 。
如IBM power PC结构下,short型数0x1234表示为12 34, int型数0x12345678表示为12 34 56 78
以IP地址127.0.0.1为例,看看两者之间是如何转换的:
1 第一步 127 . 0 . 0 . 1 把IP地址每一部分转换为8位的二进制数。
2 第二步 01111111.00000000.00000000.00000001 = 2130706433 (主机字节序)
3 然后把上面的四部分二进制数从右往左按部分重新排列,那就变为:
4 第三步 00000001.00000000.00000000.01111111 = 16777343 (网络字节序)
【示例】
1 SOCKADDR_IN addrSrv; 2 addrSrv.sin_addr.S_un.S_addr=htonl(2130706433); 3 addrSrv.sin_family=AF_INET; 4 addrSrv.sin_port=htons(6000);
先是定义了一个IP地址结构体addrSrv,然后初始化它的IP时addrSrv.sin_addr.S_un.S_addr必须是赋值IP地址的网络字节序,htonl函数的作用是把一个主机字节序转换为网络字节序,也就是上面转换过程中第二步转换为第三步的作用,127.0.0.1的主机字节序是2130706433,把主机字节序2130706433转换为网络字节序就是htonl(2130706433)=16777343,所以如果你知道网络字节序是16777343的话,addrSrv.sin_addr.S_un.S_addr=htonl(2130706433);与addrSrv.sin_addr.S_un.S_addr=16777343;是完全一样的。
1 addrSrv.sin_addr.S_un.S_addr=htonl(2130706433);//这句还可以写为下面的样子 2 addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); 3 //结果是完全一样的。 4 //可见inet_addr函数的转换作用就是上面的第一步到第三步的转换。
下面再看端口的主机字节序与网络字节序的转换。以6000端口为例。
1 第一步 00010111 01110000 = 6000 (主机字节序) 2 //端口号其实就已经是主机字节序了,首先要把端口号写为16位的二进制数,分前8位和后8位。 3 第二步 01110000 00010111 = 28695 (网络字节序) 4 //然后把主机字节序的前八位与后八位调换位置组成新的16位二进制数,这新的16位二进制数就是网络字节序的二进制表示了。
因此,如果你知道6000端口的网络字节序是28695的话。 addrSrv.sin_port=htons(6000);可以直接写为 addrSrv.sin_port=28695;结果是一样的,htons的作用就是把端口号主机字节序转换为网络字节序。
二、htonl() htons() ntohl() ntohs()及inet_ntoa() inet_addr()的用法
htonl()函数:将主机字节序转换为网络字节序
函数原型:
1 u_long PASCAL FAR htonl (u_long hostlong);
htons()函数:将主机字节序转换为网络字节序
函数原型:
1 u_short PASCAL FAR htons (u_short hostshort);
ntohl()函数:网络顺序转换成主机顺序
函数原型:
1 u_long PASCAL FAR ntohl (u_long netlong);
ntohs()函数:网络顺序转换成主机顺序
函数原型:
1 u_short PASCAL FAR ntohs (u_short netshort);
inet_ntoa()函数:接受一个in_addr结构体类型的参数并返回一个以点分十进制格式表示的IP地址字符串。
函数原型:
1 char FAR * PASCAL FAR inet_ntoa (struct in_addr in);
inet_addr()函数:需要一个字符串作为其参数,该字符串指定了以点分十进制格式表示的IP地址(例如:192.168.0.16)。
而且inet_addr函数会返回一个适合分配给S_addr的u_long类型的数值。
函数原型:
1 unsigned long PASCAL FAR inet_addr (const char FAR * cp);