• 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);
  • 相关阅读:
    Codeforces Round #425 (Div. 2) Problem A Sasha and Sticks (Codeforces 832A)
    bzoj 2301 Problem b
    bzoj 1101 [POI2007]Zap
    bzoj 2005 能量采集
    bzoj 2527 Meteors
    bzoj 2724 [Violet 6]蒲公英
    回顾树状数组
    bzoj 3237 连通图
    bzoj 2733 永无乡
    Codeforces 817C Really Big Numbers
  • 原文地址:https://www.cnblogs.com/Long-w/p/9604201.html
Copyright © 2020-2023  润新知