Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C getaddrinfo():如何区分解析失败和不可解析的主机名?_C_Linux_Sockets_Dns - Fatal编程技术网

C getaddrinfo():如何区分解析失败和不可解析的主机名?

C getaddrinfo():如何区分解析失败和不可解析的主机名?,c,linux,sockets,dns,C,Linux,Sockets,Dns,理论上,getaddrinfo(3)的返回值应允许区分无法解决的主机名和DNS服务器的问题: RETURN VALUE getaddrinfo() returns 0 if it succeeds, or one of the following nonzero error codes: EAI_ADDRFAMILY The specified network host does not have any ne

理论上,
getaddrinfo(3)
的返回值应允许区分无法解决的主机名和DNS服务器的问题:

RETURN VALUE
       getaddrinfo()  returns  0  if  it  succeeds,  or  one of the following
       nonzero error codes:

       EAI_ADDRFAMILY
              The specified network host does not have any network  addresses
              in the requested address family.

       EAI_AGAIN
              The  name  server returned a temporary failure indication.  Try
              again later.

       EAI_NODATA
              The  specified  network host exists, but does not have any net-
              work addresses defined.
(摘自
man 3 getaddrinfo

但在实践中,似乎没有什么不同:

$ ./getaddr_test www.google.invalid 80
getaddrinfo returned -2 (Name or service not known), errno is errno: 2
$ sudo vim /etc/resolv.conf # point to non-existing nameserver
$ ./getaddr_test www.google.com 80
getaddrinfo returned -2 (Name or service not known), errno is errno: 2
$ ./getaddr_test www.google.invalid 80
getaddrinfo returned -2 (Name or service not known), errno is errno: 2
$ uname -o -v
#1 SMP Debian 3.14.12-1 (2014-07-11) GNU/Linux
有没有其他方法来区分无法解析的主机名和无法访问的DNS服务器(不需要我对“已知良好”的主机名执行第二次查找)

以下是我使用的测试程序的来源:

#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main(int argc, char *argv[]) {
  struct addrinfo hints;
  struct addrinfo *result;
  int ret;

  if (argc < 3) {
    fprintf(stderr, "Usage: %s host port...\n", argv[0]);
    exit(EXIT_FAILURE);
  }

  memset(&hints, 0, sizeof(struct addrinfo));
  hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
  hints.ai_socktype = SOCK_STREAM; /* Stream socket */
  hints.ai_protocol = 0;          /* Any protocol */
  hints.ai_flags = 0;

  ret = getaddrinfo(argv[1], argv[2], &hints, &result);
  if (ret != 0) 
    printf("getaddrinfo returned %d (%s), errno is errno: %d\n",
           ret, gai_strerror(ret), errno);
  else
    printf("getaddrinfo succeeded.");
}
#包括
#包括
#包括
#包括
#包括
int main(int argc,char*argv[]){
结构addrinfo提示;
结构addrinfo*结果;
int ret;
如果(argc<3){
fprintf(stderr,“用法:%s主机端口…\n”,argv[0]);
退出(退出失败);
}
memset(&hints,0,sizeof(struct addrinfo));
hits.ai_family=AF_unsec;/*允许IPv4或IPv6*/
hints.ai_socktype=SOCK_STREAM;/*STREAM socket*/
hints.ai_protocol=0;/*任何协议*/
hints.ai_flags=0;
ret=getaddrinfo(argv[1]、argv[2]、提示和结果);
如果(ret!=0)
printf(“getaddrinfo返回%d(%s),错误号为错误号:%d\n”,
雷特,盖乌斯特雷罗(雷特),厄尔诺);
其他的
printf(“getaddrinfo成功”);
}

我认为它之所以不区分这一点,是因为它有多个用于解析名称的信息源。大多数Linux使用NSS聚合这些源,默认情况下使用/etc/hosts基于文件的解析以及DNS解析(但可能是LDAP和其他)

您可以在nsswitch.conf文件中将“hosts”设置为“dns”的情况下再次尝试测试,但即使该解决方案有效,也不会非常可靠


我能想象的唯一完整的解决方案是让你自己联系DNS服务器。如果你不能为他们打开一个插座,那么你知道他们是联系不到的。如果可以,但名称无法解析,则知道它是无效名称。

在查看netdb.h之后,我发现返回值-2等于EAI_NONAME。