• htons/ntohs、inet_aton/inet_ntoa、inet_pton/inet_ntop函数详解


    在介绍htons等函数之前,必须先介绍网络字节序与主机字节序

    网络字节序和主机字节序

    网络字节顺序NBO(Network Byte Order): 按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题。
    主机字节顺序(HBO,Host Byte Order): 不同的机器HBO不相同,与CPU设计有关,数据的顺序是由cpu决定的,而与操作系统无关。

    主机字节序就是我们平常说的大端和小端模式:不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序。引用标准的Big-EndianLittle-Endian的定义如下:
    a)Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
    b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

    网络字节序:4个字节的32bit值以下面的次序传输:首先是0~7bit,其次8~15bit,然后16~23bit,最后是24~31bit。这种传输次序称作大端字节序。由于TCP/IP首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序。

    注意:在将一个地址绑定到socket的时候,请先将主机字节序转换成为网络字节序再赋给socket,而不要假定主机字节序跟网络字节序一样使用的是Big-Endian。

    htonl、htons、ntohl、ntohs

    #include <arpa/inet.h>	//函数头文件
    
    uint32_t htonl(uint32_t hostlong);//32位的主机字节序转换到网络字节序
    uint16_t htons(uint16_t hostshort);//16位的主机字节序转换到网络字节序
    uint32_t ntohl(uint32_t netlong);//32位的网络字节序转换到主机字节序
    uint16_t ntohs(uint16_t netshort);//16位的网络字节序转换到主机字节序
    

    这里通过调用两个函数htons()htolnl()分别用来将 端口和IP地址转换成网络字节序;
    这两个函数名中的 h表示host, n表示network, s表示short(2字节/16位), l表示long(4字节/32位)。
    因为端口号16位的,所以我们用htons()把端口号从主机字节 序转换成网络字节序, 而IP地址32位的,所以我们用htonl()函数把IP地址从主机字节序转换成网络字节序
    hostlongnetlong参数:可当作是4字节(32位)整数;
    hostshortnetshort参数:可当作是2字节(16位)整数。

    其它函数同理可得,这里不再赘述。

    这里注意: uint8_t / uint16_t / uint32_t /uint64_t类型解释如下,如以了解,可自行忽略。
    按照posix标准,一般整形对应的*_t类型为:

    1字节     uint8_t
    2字节     uint16_t
    4字节     uint32_t
    8字节     uint64_t
    

    这些数据类型是 C99 中定义的,具体定义在:/usr/include/stdint.h ISO C99: 7.18 Integer types <stdint.h>

    /* There is some amount of overlap with <sys/types.h> as known by inet code */
    #ifndef __int8_t_defined
    # define __int8_t_defined
    typedef signed char             int8_t; 
    typedef short int               int16_t;
    typedef int                     int32_t;
    # if __WORDSIZE == 64
    typedef long int                int64_t;
    # else
    __extension__
    typedef long long int           int64_t;
    # endif
    #endif
    
    /* Unsigned.  */
    typedef unsigned char           uint8_t;
    typedef unsigned short int      uint16_t;
    #ifndef __uint32_t_defined
    typedef unsigned int            uint32_t;
    # define __uint32_t_defined
    #endif
    #if __WORDSIZE == 64
    typedef unsigned long int       uint64_t;
    #else
    __extension__
    typedef unsigned long long int  uint64_t;
    #endif
    

    inet_aton、inet_ntoa(IPv4)

    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    int inet_aton(const char *cp, struct in_addr *inp);//点分十进制字符串转换成网络字节序
    char *inet_ntoa(struct in_addr in);	//网络字节序转换成点分十进制字符串
    

    作用inet_aton()点分十进制IP地址转换为网络字节序IP地址存储在in_addr结构体当中;
    cp参数:字符串常量(点分十进制IP地址)
    inp参数:转换结果存储在IPv4结构体中;
    函数成功执行则返回该网络字节序表示的无符号整数

    作用inet_ntoa()网络字节序IP地址转换为点分十进制IP地址
    in参数:IPv4结构体当中IP地址;
    函数成功指向则返回指向点分十进制字符串指针

    注意:对inet_aton()的调用传递的是指向结构体的指针,而对inet_ntoa()的调用传递的是结构体本身

    inet_pton、inet_ntop(IPv4与IPv6)

    #include <arpa/inet.h>
    
    int inet_pton(int family, const char *strptr, void *addrptr);
    const char * inet_ntop(int family, const void *addrptr, char *strptr, size_t len);
    

    功能inet_pton()函数用于将文本字符串转换成网络字节序的二进制地址;
    family参数:AF_INET(ipv4)、AF_INET6(ipv6);
    strptr参数:指针指向等待转换的字符串;
    addrptr参数:转换成功的二进制结果;
    若成功则返回值为1,否则如果所指定的family而言输入字符串不是有效的表达式格式,那么返回值为0。

    功能inet_ntop()函数用于将网络字节序的二进制地址转换成文本字符串;
    family参数:AF_INET(ipv4)、AF_INET6(ipv6);
    strptr参数:指针指向等待转换的字符串,不可以是一个空指针;
    addrptr参数:转换成功的二进制结果;
    调用者必须为目标存储单元分配内存并指定其大小,调用成功时,这个指针就是该函数的返回值。
    len参数:目标 存储单元的大小,以免该函数溢出其调用者的缓冲区。如果len太小,不足以容纳表达式结果,那么返回一个空指针,并置为errno为ENOSPC。

  • 相关阅读:
    重构后的ConditionHelper
    重构ConditionHelper
    用shell求两个文件的差集
    文件落盘的逻辑
    [转]undefined reference问题总结
    动态生成xml文件
    32位,64位的一些问题
    树数据结构的实际应用
    线程池中的栅栏
    关于线程池的理解
  • 原文地址:https://www.cnblogs.com/Tavi/p/12514055.html
Copyright © 2020-2023  润新知