【问题标题】:What's wrong with gethostbyname?gethostbyname 有什么问题?
【发布时间】:2011-10-04 08:38:21
【问题描述】:

我正在使用我在http://www.kutukupret.com/2009/09/28/gethostbyname-vs-getaddrinfo/ 中找到的这段代码的 sn-p 来执行 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

但该程序似乎可以工作。

知道为什么吗?

【问题讨论】:

  • 我刚刚尝试了 en.wikipedia.org/wiki/Getaddrinfo 中的代码获取 getaddrinfo,但是 10.1.1 sill 在 10.1.0.1 中解析...这是一个错误吗?我错过了什么吗?

标签: c linux gethostbyname


【解决方案1】:

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

描述

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

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

a.b.c.d 当指定四个部分时,每个部分都被解释为一个数据字节,并从左到右分配给互联网地址的四个字节。

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

例如,您可以阅读有关此there 的更多信息。

【讨论】:

  • 有什么说gethostbyname应该调用inet_aton吗?
  • @cHao:当 gethostbyname() 被赋予一个虚线 ip 作为参数时(如在 OP 的场景中),它使用 inet_aton():“如果名称是 IPv4 或 IPv6 地址,则不执行查找gethostbyname() 只是将 name 复制到 h_name 字段中,并将其 struct in_addr 等效项复制到返回的 hostent 结构的 h_addr_list[0] 字段中”
【解决方案2】:

POSIX.2004 说:

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

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

在我的系统上,man page 是这样说的:

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

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

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

【讨论】:

  • 除了frominet_addr, "abc 指定三部分地址时,最后一部分应解释为16位数量,放在网络地址最右边的两个字节中。这使得三部分地址格式便于将B类网络地址指定为“128.net.host”。所以,Linux表示如何处理点分IP地址,而inet_addr定义10.1.1是点分地址含义与10.1.0.1 相同,因此提问者观察到的行为是在 Linux 上定义和预期的。
猜你喜欢
  • 1970-01-01
  • 2011-07-05
  • 1970-01-01
  • 1970-01-01
  • 2021-06-09
  • 2014-08-12
  • 2010-12-23
  • 2010-10-24
相关资源
最近更新 更多