为什么inet_ntoa总是返回0.0.0.0作为ip地址?

时间:2017-03-09 18:06:58

标签: c sockets ip hostname

我不明白,因为以下代码总是以0.0.0.0的价格返回google.com的IP地址。我需要使用inet_ntoa而不是其他功能。任何人都可以帮我弄清楚pb吗?

#include<stdio.h> //printf
#include<string.h> //memset
#include<stdlib.h> //for exit(0);
#include<sys/socket.h>
#include<errno.h> //For errno - the error number
#include<netdb.h> //hostent
#include<arpa/inet.h>

int hostname_to_ip(char *  , char *);

int main(int argc , char *argv[])
{
    if(argc <2)
    {
        printf("Please provide a hostname to resolve");
        exit(1);
    }

    char *hostname = argv[1];
    char ip[100];

    hostname_to_ip(hostname , ip);
    printf("%s resolved to %s" , hostname , ip);

    printf("\n");

}
/*
    Get ip from domain name
 */

int hostname_to_ip(char *hostname , char *ip)
{
    int sockfd;  
    struct addrinfo hints, *servinfo, *p;
    struct sockaddr_in *h;
    int rv;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6
    hints.ai_socktype = SOCK_STREAM;

    if ( (rv = getaddrinfo( hostname , "http" , &hints , &servinfo)) != 0)    
    {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }

    // loop through all the results and connect to the first we can
    for(p = servinfo; p != NULL; p = p->ai_next) 
    {
        h = (struct sockaddr_in *) p->ai_addr;
        strcpy(ip , inet_ntoa( h->sin_addr ) );
    }

    freeaddrinfo(servinfo); // all done with this structure
    return 0;
}

它实际上是从http://www.binarytides.com/hostname-to-ip-address-c-sockets-linux/获取的代码,但我的代码几乎都在做同样的事情,特别是它使用了我正在寻找的相同功能。

我编译:     $ gcc hostname_to_ip.c && ./a.out www.google.com

1 个答案:

答案 0 :(得分:1)

getaddrinfo()函数返回一个链接的地址列表,其中客户端应该选择。您可以通过&#34;提示&#34;来影响列表中包含的地址。传递给该函数的对象。在使用inet_ntoa()处理获得的地址时,您假设使用IPv4。那么,告诉getaddrinfo()您只对IPv4地址感兴趣是有道理的:

hints.ai_family = AF_INET;

我可以使用您的原始代码重现您的结果,但进行一次修改会让我找到一个合理的IPv4地址。

虽然你走了getaddrinfo()提供的地址列表,当你在不检查地址系列的情况下转换为struct sockaddr_in *时,你假设其中的每个地址都在家庭中AF_INET。那是不安全的。此外,您使用下一个转换地址字符串覆盖每个转换后的地址字符串,因此,如果getaddrinfo()能够优先处理您最有可能需要的地址,那么您可以将其转换为破损地址。

如果您没有指定只需要IPv4地址,那么在决定是否使用IPv4地址之前,至少应该检查每个返回的地址的系列。此外,您只需要返回一个,所以一旦找到可以使用的循环,您也可以摆脱循环。