【发布时间】:2021-06-03 15:26:46
【问题描述】:
我正在测试一条错误路径,该路径需要我从 getaddrinfo 中删除请求。我设置了 2 个虚拟机:
- RHEL 7.9
- Ubuntu 20
两台机器上的代码相同,只需调用 test.com 的 getaddrinfo。我阻止了所有传入的数据包以模拟 getaddrinfo 的请求被丢弃,但是在完全相同的场景中,两个操作系统的执行方式不同。
- RHEL 在 12 秒后超时并出现错误 EAI_NONAME(没有这样的文件或目录)
- Ubunutu 在 20 秒后超时并出现错误 EAI_AGAIN(资源暂时不可用)
所以我的两个问题是:
- 为什么这些会给出 2 个不同的错误?
- 为什么超时不同,它们是在哪里定义的?我试图查看 linux 源代码,但无法弄清楚
代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int main (void)
{
struct addrinfo hints, *res, *result;
int errcode;
char addrstr[100];
void *ptr;
memset (&hints, 0, sizeof (hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags |= AI_CANONNAME;
errcode = getaddrinfo ("test.com", NULL, &hints, &result);
if (errcode != 0)
{
perror ("getaddrinfo");
return -1;
}
res = result;
while (res)
{
inet_ntop (res->ai_family, res->ai_addr->sa_data, addrstr, 100);
switch (res->ai_family)
{
case AF_INET:
ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr;
break;
case AF_INET6:
ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
break;
}
inet_ntop (res->ai_family, ptr, addrstr, 100);
printf ("IPv%d address: %s (%s)\n", res->ai_family == PF_INET6 ? 6 : 4,
addrstr, res->ai_canonname);
res = res->ai_next;
}
freeaddrinfo(result);
return 0;
}
编译:
gcc test.c
RHEL resolv.conf:
search ht.home
nameserver 192.168.0.1
nameserver [IPV6 address 1]
nameserver [IPV6 address 2]
Ubuntu:
nameserver 127.0.0.53
options edns0 trust-ad
search ht.home
【问题讨论】:
-
发布代码和编译参数。
-
@AndrewHenle 已发布。最初没有包含它,因为它们都是同一个程序并且编译方式相同,所以认为它不相关
-
resolv.conf在两种环境中看起来都一样吗? -
@larsks 不,它们是不同的。我会在描述中发布
-
我将其归结为您正在与不同的解析器交谈:在您的 Ubuntu 系统上,您正在与本地
systemd-resolved实例交谈,而在 RHEL 系统上您正在交谈到 192.168.0.1 上运行的任何东西。这很像两个解析器的反应不同。如果您修改 ubuntu resolv.conf 使其看起来像 RHEL,代码的行为是否会发生变化?
标签: c linux networking getaddrinfo