5、【Linux网络编程】socket中htonl() htons() ntohl() ntohs()及inet_ntoa() inet_addr()的用法

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);
原文地址:https://www.cnblogs.com/Long-w/p/9604201.html