首页 > 解决方案 > 为什么 getnameinfo() 检索重复的地址?

问题描述

我使用 BSD 套接字 API 中的 getnameinfo() 函数从主机获取地址,我想获取所有可用的地址:

 struct addrinfo hints;
  memset(&hints, 0, sizeof(hints));
  hints.ai_flags = AI_ALL;
  struct addrinfo *peer_address;
  if (getaddrinfo(argv[1], NULL, &hints, &peer_address)) {
    fprintf(stderr, "getaddrinfo() ERROR.\n");
    return EXIT_FAILURE;
  }

  printf("Remote address(es):\n");
  struct addrinfo *address = peer_address;

  while((address = address->ai_next)) {
    char address_buffer[100];
    getnameinfo(address->ai_addr, address->ai_addrlen,
        address_buffer, sizeof(address_buffer), 0, 0, NI_NUMERICHOST);
    printf("\t> %s\n", address_buffer);
  }

  freeaddrinfo(peer_address);

并构建并运行此代码,我得到该输出:

$lookup google.com
Remote address(es):
   > 172.217.203.100
   > 172.217.203.100
   > 172.217.203.102
   > 172.217.203.102
   > 172.217.203.102
     .
     .
     .
   > 2607:f8b0:400c:c07::8a
   > 2607:f8b0:400c:c07::8a
   > 2607:f8b0:400c:c07::8a

为什么每个 IP 地址都要打印两三遍?

标签: csocketsnetworking

解决方案


您会看到过度未指定的hints变量的影响,这通常会将列表缩小到您所要求的范围内。

当您询问所有内容时,似乎对于每个 IP 地址,都有一个用于 tcp ( SOCK_STREAM)、udp ( SOCK_DGRAM) 以及 IP ( SOCK_RAW) 的条目,但在仅查找 IP 地址的情况下——而不是服务——我看不出这有什么用。

解决此问题的简单方法是更新您的提示:

    struct addrinfo hints;
    memset(&hints, 0, sizeof hints);
    hints.ai_flags = AI_ALL;
    hints.ai_socktype = SOCK_RAW;   // ADD ME

此外,您的循环确实跳过了第一个条目,因此替代可能是:

    for (struct addrinfo *address = peer_address
       ;  address != 0
       ;  address = address->ai_next )
    {
        // do stuff

一个有用的参考:套接字编程中 addrinfo 名称的“提示”是什么意思


推荐阅读