gethostbyname出了什么问题?

Ott*_*ana 7 c linux gethostbyname

我使用此代码段时,我发现在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;
}
Run Code Online (Sandbox Code Playgroud)

我面临着一个奇怪的事实

./test www.google.com
Hostname: www.l.google.com
IP Address: 209.85.148.103
Run Code Online (Sandbox Code Playgroud)

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

./test 10.1.1
Hostname: 10.1.1
IP Address: 10.1.0.1
Run Code Online (Sandbox Code Playgroud)

我希望会出现如下错误

./test www.google
gethostbyname(): : Unknown host
Run Code Online (Sandbox Code Playgroud)

但该计划似乎有效.

知道为什么吗?

Igo*_*hov 19

它不是bug,而是inet_aton()函数的一个特性:

描述

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

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

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

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

例如,您可以在那里阅读更多相关信息.

  • @cHao:为gethostbyname()提供一个点分ip作为参数时(如在OP中的情况),则它使用inet_aton():“如果名称是IPv4或IPv6地址,则不执行查找,并且gethostbyname()只是将名称复制到h_name字段及其结构in_addr等效于返回的hostent结构的h_addr_list [0]字段” (2认同)

San*_*ker 7

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在系统上实现的更多信息,可以查看文档中的函数和/或源代码(如果有).

  • 除了来自`inet_addr`,"abc指定三部分地址时,最后一部分应解释为16位数量并放在网络地址的最右边两个字节中.这使得三部分地址格式方便将B类网络地址指定为"128.net.host".因此,Linux说明如何处理虚线IP地址,`inet_addr`定义`10.1.1`是一个虚线地址,意思是与10.1相同. 0.1`,因此提问者观察到的行为是在Linux上定义和预期的. (3认同)