曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 6880|回复: 0
打印 上一主题 下一主题

inet_pton() -- 将 IPv4/IPv6 地址从 text 转换到二进制形式

[复制链接]

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
跳转到指定楼层
楼主
发表于 2012-6-8 23:29:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
为了方便阅读,我们平时看到的是点分十进制的 IPv4 地址和以冒号分隔的 IPv6  地址。但是在网络上,编程里传输的不能是这两种形式,而是必须先转换为二进制形式,inet_pton() 函数所做的事情正是如此。函数定义如下:
[Plain Text] 纯文本查看 复制代码
#include <arpa/inet.h>
int inet_pton(int af, const char *src, void *dst);

第 1 个参数 af 要么是 AF_INET,要么是 AF_INET6,前者表示转换的是 IPv4 地址,后者表示转换的是 IPv6 地址。
第 2 个参数 src 可以是点分十进制的 IPv4 地址形式,也可以是以冒号分隔的 IPv6 地址形式。
第 3 个参数 dst 用来存储转换后的二进制形式。

测试代码:
[C++] 纯文本查看 复制代码
#include <arpa/inet.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <string.h>

       int
       main(int argc, char *argv[])
       {
         struct in_addr addr4;
           struct in6_addr addr6;

           int domain, s, i;
           char str[INET6_ADDRSTRLEN];

           if (argc != 3) {
               fprintf(stderr, "Usage: %s {i4|i6|<num>} string\n", argv[0]);
               exit(EXIT_FAILURE);
           }

           domain = (strcmp(argv[1], "i4") == 0) ? AF_INET :
                    (strcmp(argv[1], "i6") == 0) ? AF_INET6 : atoi(argv[1]);
       
       if (domain == 4 || domain == AF_INET) {
        domain = AF_INET;
            s = inet_pton(domain, argv[2], &addr4);
                if (s <= 0) {
                    if (s == 0)
                       fprintf(stderr, "Not in presentation format");
                    else 
                       perror("inet_pton");
                 
                    exit(EXIT_FAILURE);
               }
          
              fprintf(stdout, "Network byte order: %u\n",addr4.s_addr);
      }
      else if (domain == 6 || domain == AF_INET6) {
        domain = AF_INET6;
            s = inet_pton(domain, argv[2], &addr6);
                if (s <= 0) {
                    if (s == 0)
                       fprintf(stderr, "Not in presentation format");
                    else 
                       perror("inet_pton");
                 
                    exit(EXIT_FAILURE);
               }
                  fprintf(stdout, "Network byte order: ");
         for (i = 0; i < 16; i++)
            fprintf(stdout, "%u ", addr6.__in6_u.__u6_addr8[i]);
        printf ("\n");  
    }

      else {
          fprintf(stderr, "Usage: %s {i4|i6|<num>} string\n", argv[0]);
          exit(EXIT_FAILURE);
      }
    

    if (domain == AF_INET) {
           if (inet_ntop(domain, &addr4, str, INET6_ADDRSTRLEN) == NULL) {
               perror("inet_ntop");
               exit(EXIT_FAILURE);
           }
           printf("%s\n", str);
    } else if (domain == AF_INET6) {
           if (inet_ntop(domain, &addr6, str, INET6_ADDRSTRLEN) == NULL) {
               perror("inet_ntop");
               exit(EXIT_FAILURE);
           }
           printf("%s\n", str);
    }
      

           exit(EXIT_SUCCESS);
  }

代码中  INET6_ADDRSTRLEN 在netinet/in.h (该头文件由 arpa/inet.h 文件包含)文件中被定义为: #define INET6_ADDRSTRLEN 46 。

结构 struct in_addr 的定义为:
[C++] 纯文本查看 复制代码
/* Internet address.  */
typedef uint32_t in_addr_t;
struct in_addr
  {
    in_addr_t s_addr;
  };


结构 struct in6_addr 定义为:
[C++] 纯文本查看 复制代码
/* IPv6 address */
struct in6_addr
  {
    union
      {
        uint8_t __u6_addr8[16];
#if defined __USE_MISC || defined __USE_GNU
        uint16_t __u6_addr16[8];
        uint32_t __u6_addr32[4];
#endif
      } __in6_u;
#define s6_addr                 __in6_u.__u6_addr8
#if defined __USE_MISC || defined __USE_GNU
# define s6_addr16              __in6_u.__u6_addr16
# define s6_addr32              __in6_u.__u6_addr32
#endif
  };

其中 uint8_t 被定义为 unsigned char 类型,如果要用 printf() 函数来打印该类型,格式控制符为 %u 。

运行输出:
# ./inet_pton i6 1:0:0:0:0:0:0:8
Network byte order: 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 8
1::8
# ./inet_pton i6 0:0:0:0:0:FFFF:204.152.189.116
Network byte order: 0 0 0 0 0 0 0 0 0 0 255 255 204 152 189 116
::ffff:204.152.189.116
# ./inet_pton i4 184.22.147.23
Network byte order: 395515576
184.22.147.23
关于 IPV6 的地址记录介绍可参考:《IPv6 记法 》。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-5-9 19:36 , Processed in 0.062858 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表