8

我正在使用在http://www.kutukupret.com/2009/09/28/gethostbyname-vs-getaddrinfo/中找到的这段代码来执行 dns 查找

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

int main(int argc, char *argv[ ]) {
    struct hostent *h;

    /* error check the command line */
    if(argc != 2) {
        fprintf(stderr, "Usage: %s hostname\n", argv[0]);
        exit(1);
    }

    /* get the host info */
    if((h=gethostbyname(argv[1])) == NULL) {
        herror("gethostbyname(): ");
        exit(1);
    }
    else     
        printf("Hostname: %s\n", h->h_name);

    printf("IP Address: %s\n", inet_ntoa(*((struct in_addr *)h->h_addr)));     
    return 0;
}

我正面临一个奇怪的事实

./test www.google.com
Hostname: www.l.google.com
IP Address: 209.85.148.103

工作正常,但如果我尝试解析不完整的 IP 地址,我会得到这个

./test 10.1.1
Hostname: 10.1.1
IP Address: 10.1.0.1

我预计会出现如下错误

./test www.google
gethostbyname(): : Unknown host

但该程序似乎有效。

知道为什么吗?

4

2 回答 2

20

这不是一个错误,而是 inet_aton() 函数的一个特性:

描述

inet_aton() 函数以 Internet 标准点表示法将指定的字符串转换为网络地址,并将地址存储在提供的结构中。

使用点表示法指定的值采用以下形式之一:

abcd当指定四个部分时,每个部分都被解释为一个数据字节,并从左到右分配给 Internet 地址的四个字节。

abc 当指定一个三部分地址时,最后一部分被解释为一个 16 位的数量并放置在网络地址的最右边的两个字节中。这使得三部分地址格式便于将 B 类网络地址指定为 128.net.host。

例如,您可以在此处阅读更多相关信息。

于 2011-07-13T10:40:11.007 回答
8

POSIX.2004说:

gethostbyname() 的 name 参数应为节点名;未指定传递数字地址字符串时 gethostbyname() 的行为。对于 IPv4,数字地址字符串应采用 inet_addr() 中描述的点分十进制表示法。

因此,从 POSIX 的角度来看,在传递一个 IP 地址时,您不能期待任何事情。

在我的系统上,手册页这样说:

如果 name 是 IPv4 或 IPv6 地址,则不执行查找,gethostbyname() 只需将 name 复制到 h_name 字段中,并将其 struct in_addr 等效项复制到返回的 hostent 结构的 h_addr_list[0] 字段中。

它没有说明如果您传递一个不完整的 IP 地址会发生什么,因此任何事情都可能发生,包括您观察到的行为。

有关如何gethostbyname在您的系统上实现的更多信息,您可以查看函数文档和/或源代码(如果可用)。

于 2011-07-13T10:15:12.637 回答