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

标签 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

最佳答案

getaddrinfo() 函数返回一个地址链接列表,客户端需要在其中进行选择。您可以通过传递给该函数的“提示”对象来影响列表中包含哪些地址。在使用 inet_ntoa() 处理获取的地址时,您假设使用的是 IPv4。那么,告诉 getaddrinfo() 您只对 IPv4 地址感兴趣是有意义的:

hints.ai_family = AF_INET;

我可以用您的原始代码重现您的结果,但进行这一修改后我会得到一个看起来合理的 IPv4 地址。

虽然您确实遍历了 getaddrinfo() 提供的地址列表,但当您在不检查地址族的情况下转换为 struct sockaddr_in * 时,您假设 其中的每个地址都属于 AF_INET 系列。那是不安全的。此外,您会用下一个转换后的地址字符串覆盖每个转换后的地址字符串,因此,如果 getaddrinfo() 很好地确定了您最可能需要的地址的优先级,那么您就会将其转化为损坏。

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

关于c - 为什么 inet_ntoa 总是返回 0.0.0.0 作为 ip 地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42702460/

相关文章:

c - 只有一次 write() 调用通过套接字连接发送数据

tcp - 如何在局域网中找到我的服务器?

c - 调用静态库函数时出现段错误

c - 显示ASCII字符的十六进制值

客户端和服务器端的 Java 套接字问题

postgresql - 无法使用 Host = localhost 连接到在 docker 中运行的 Postgresql

OpenCV 和与 IP Camera 的连接 - 我的相机型号

c - 创建一个二维数组,用户给出数组的大小 (n*n),并且数组用随机数 [1-10] 填充,无需 malloc

链接到 Ox 的 C 库

c# - IPv4 映射的 IPv6 地址