曲径通幽论坛

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

getaddrinfo() -- 网络地址和服务转换

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34387
跳转到指定楼层
楼主
发表于 2012-6-11 10:38:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
getaddrinfo() 函数用于网络地址和服务转换,其原型声明如下:
[C++] 纯文本查看 复制代码
#include <sys/types.h>
       #include <sys/socket.h>
       #include <netdb.h>
int getaddrinfo(const char *node, const char *service,
                       const struct addrinfo *hints,
                       struct addrinfo **res);


第 1 个参数 node 是一个主机名或地址串( IPv4 的点分十进制或 IPv6 十六进制数串 )。

第 2 个参数 service 是一个服务名或十进制端口号数串。

第 3 个参数 hints 是一个 struct addrinfo 结构的指针(也可以为空)。如果该指针非空时,可以在所指向的结构中填入期望返回的信息类型的暗示。比如说,如果指定的服务既支持 TCP 也支持 UDP,如果我们希望返回的只是 UDP 的信息,那么可以将 hints 结构中的 ai_socktype 成员设置为 SOCK_DGRAM 。struct addrinfo 结构定义如下:
[C++] 纯文本查看 复制代码
struct addrinfo {
               int              ai_flags;
               int              ai_family;
               int              ai_socktype;
               int              ai_protocol;
               size_t           ai_addrlen;
               struct sockaddr *ai_addr;
               char            *ai_canonname;
               struct addrinfo *ai_next;
           };

其中,
ai_family : 该成员指定期望返回的地址族,比如 AF_INET 或 AF_INET6 。如果指定为 AF_UNSPEC (宏定义中,该值为 0)那么表示让函数返回所有可能的地址族,即可以是 IPv4 或者是 IPv6 。

ai_socktype : 该成员指出 socket 类型,比如 SOCK_STREAM 或者 SOCK_DGRAM 。如果指定为 0,那么函数返回所有可能的类型。

ai_protocol : 该成员指定协议,0 或者 IPPROTO_xxx (IPPROTO_ICMP, IPPROTO_TCP  等) 。如果指定为 0,那么函数返回所有可能的类型。

ai_flags : 该成员提供额外的选项,有多个可用标志值,这些标志可用或符号结合起来,这些标志值有:

AI_PASSIVE : 套接字将用于被动打开。

AI_CANONNAME : 让 getaddrinfo() 返回主机的规范名

AI_NUMERICHOST : 此时 node 参数必须是一个地址串,该标志用以防止任何类型的名字到地址映射,也就是说不需要进行从网址到 IP 的 DNS 查询。

AI_NUMERICSERV :  此时 service 参数必须是一个十进制端口号数串,该标志用以防止任何类型的名字到服务映射,也就是说只需根据端口号就能查到相应的服务名(gethostbyport() 函数) 。

AI_V4MAPPED : 如果同时指定了 ai_family 成员的值为 AF_INET6,那么如果没有可用的 AAAA 记录( IPv4 在 DNS 里用的是 A 记录,一个 A 记录把一个主机名映射成一个 32 位的 IPv4 地址;而 AAAA 记录把一个主机名映射成一个 128 位的 IPv6 地址,因此 “四A” 的意思就是 128 位是 32 位的 4 倍),那么就返回 A 记录对应的 IPv4 记录对应的 IPv4 映射的 IPv6 地址(参考:IPv6 记法 )。

AI_ALL : 如果同时指定 AI_V4MAPPED 标志,那么除了返回与 AAAA 记录对应的 IPv6 地址外,还返回与 A 记录对应的 IPv4 映射的 IPv6 地址。

AI_ADDRCONFIG : 按照所在主机的配置选择返回地址类型。如果主机上有一个或多个接口(除了 lookback 接口外) 时,查找其它配置的地址类型(IPv4 和 IPv6) 。


第 4 个参数 res 是个 struct addrinfo 结构指针的指针。getaddrinfo() 函数会将返回的信息存储在它动态分配的内存空间里,这些空间是由一个 struct addrinfo 结构的单向链表所占据,链表中的每个结构由 ai_next 成员指针所连接。

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

int
lookup_host (const char *host)
{
  struct addrinfo hints, *res;
  int errcode;
  char addrstr[100];
  void *ptr;

  memset (&hints, 0, sizeof (hints));
  hints.ai_family = PF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags |= AI_CANONNAME;

  errcode = getaddrinfo (host, NULL, &hints, &res);
  if (errcode != 0)
    {
      perror ("getaddrinfo");
      return -1;
    }

  printf ("Host: %s\n", host);
  while (res)
    {
      inet_ntop (res->ai_family, res->ai_addr->sa_data, addrstr, 100);

      switch (res->ai_family)
        {
        case AF_INET:
          ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr;
          break;
        case AF_INET6:
          ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
          break;
        }
      inet_ntop (res->ai_family, ptr, addrstr, 100);
      printf ("IPv%d address: %s (%s)\n", res->ai_family == PF_INET6 ? 6 : 4,
              addrstr, res->ai_canonname);
      res = res->ai_next;
    }

  return 0;
}

int
main (int argc, char *argv[])
{
  if (argc < 2)
    exit (1);
  return lookup_host (argv[1]);
}

运行输出:
# ./getaddrinfo www.groad.net
Host: www.groad.net
IPv4 address: 218.77.79.100 (lb.360wzb.com)

# ./getaddrinfo www.mobaoge.net
Host: www.mobaoge.net
IPv4 address: 59.57.12.38 (common.xgslb.net)
IPv4 address: 113.107.43.238 ((null))
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-5-20 16:04 , Processed in 0.061155 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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