Когда я делаю getaddrinfo для localhost, я не получаю 127.0.0.1 - PullRequest
2 голосов
/ 23 апреля 2011

Я все еще изучаю сокеты и неясно, почему это не распечатывает 127.0.0.1.Даже если я заменю слово localhost на 127.0.0.1, я получу несколько других ip, которые, как мне кажется, являются моим маршрутизатором или чем-то еще.Я всегда думал, что это должно вернуть 127.0.0.1.Вот вывод, который я получаю:

hostname: 28.30.0.0
hostname: 28.30.0.0
hostname: 28.30.0.0
hostname: 28.30.0.0
hostname: 16.2.0.0
hostname: 16.2.0.0

Вот основной код:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>

int main()
{
    struct addrinfo* feed_server = NULL;

    getaddrinfo("localhost", NULL, NULL, &feed_server);
    struct addrinfo *res;
    for(res = feed_server; res != NULL; res = res->ai_next)
    {   
        printf("hostname: %s\n", inet_ntoa(*((struct in_addr*)(res->ai_addr))));
    } 

    return 0;
}

Ответы [ 3 ]

4 голосов
/ 23 апреля 2011

res->ai_addr имеет тип struct sockaddr*, а не struct in_addr*.

Вам нужно сделать что-то вроде этого:

for(res = feed_server; res != NULL; res = res->ai_next)
{
    /* ideally look at the sa_family here to make sure it is AF_INET before casting */
    struct sockaddr_in* saddr = (struct sockaddr_in*)res->ai_addr;
    printf("hostname: %s\n", inet_ntoa(saddr->sin_addr));
} 
3 голосов
/ 12 декабря 2011

Вы должны использовать подсказки для вызова getaddrinfo.Потому что для разрешения "localhost" или любой записи /etc/hosts необходимо установить hints.af_family AF_INET.

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>

int main()
{

   struct addrinfo hints;
   memset(&hints, 0, sizeof(struct addrinfo));
   hints.ai_family = AF_INET;
   getaddrinfo("localhost", NULL, &hints, &feed_server);
   struct addrinfo *res;
   for(res = feed_server; res != NULL; res = res->ai_next){   
      struct sockaddr_in* saddr = (struct sockaddr_in*)res->ai_addr;
      printf("hostname: %s\n", inet_ntoa(saddr->sin_addr))
   } 
   return 0;
}
1 голос
/ 21 января 2016

С исходным кодом есть две проблемы:

  1. Член ai_addr указывает на sockaddr, а не на struct in_addr, поэтому приведение его так всегда приведет к неверным результатам.
  2. Если вы не передадите подсказку, отличную от NULL, и если элемент af_family имеет значение AF_INET, вы не можете ожидать, что все возвращаемые адреса будут IPv4 (тип struct sockaddr_in).Таким образом, вы можете предоставить подсказки для указания IPv4 или проверить член af_family получающихся структур addrinfo.

Одна вещь, которую я обычно вижу по крайней мере в системах Linux, состоит в том, что getaddrinfo для localhost обычно возвращает IPv6 ::Сначала адрес 1.

По напечатанным адресам я могу сказать, что вы работаете в ОС, которая включает в себя длину sockaddrs в структуре.Например, определение struct sockaddr в OS X выглядит следующим образом:

 struct sockaddr {
      __uint8_t       sa_len;         /* total length */
      sa_family_t     sa_family;      /* [XSI] address family */
      char            sa_data[14];    /* [XSI] addr value (actually larger) */
 };

Как для struct sockaddr_in, так и для sockaddr_in6 самый следующий член после sa_family - это порт, который всегда составляет два байта.Поэтому, когда вы приведете любую из этих структур к структуре in_addr, вы получите адрес sa_len.sa_family.0.0 (при условии, что вы не предоставляете порт для getaddrinfo - если вы предоставите порт, 0.0 будет заменен байтом портов.значения).

Итак, информация gettaddr возвращает вам два IPv6-адреса: 28.30.0.0 - sizeof struct sockaddr_in6 = 28 и af_family = 30

и два IPv4-адреса: 16.2.0.0 - sizeof struct sockaddr_in= 16 и af_family = 2

Чтобы сделать это правильно, вы можете сделать то, что сказал другой ответ, и использовать getnameinfo.Однако использование inet_ntop (не inet_ntoa) может быть одинаково хорошим.

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h> /* for memset */

int main()
{
   char addr_buf[64];
   struct addrinfo* feed_server = NULL;

   memset(addr_buf, 0, sizeof(addr_buf));

   getaddrinfo("localhost", NULL, NULL, &feed_server);
   struct addrinfo *res;
   for(res = feed_server; res != NULL; res = res->ai_next)
   {   
       if ( res->ai_family == AF_INET )
       {
          inet_ntop(AF_INET, &((struct sockaddr_in *)res->ai_addr)->sin_addr, addr_buf, sizeof(addr_buf));
       }
       else
       {
          inet_ntop(AF_INET6, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, addr_buf, sizeof(addr_buf));
       }

       printf("hostname: %s\n", addr_buf); 
   } 

   return 0;
}

`` `

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...