gpt4 book ai didi

c - 如果 getaddrinfo 失败一次,它将永远失败(即使在网络准备就绪之后)

转载 作者:IT王子 更新时间:2023-10-29 00:32:06 26 4
gpt4 key购买 nike

我正在编写一个作为 systemd service 运行的 C 应用程序在启动时(发行版:Arch Linux)并且应该连接到服务器。因为应用程序是在启动时运行的,所以最终会发生网络连接尚未建立的情况。这自然会导致需要一个的第一个函数失败,在我的例子中是 getaddrinfo

所以我想我会写一个循环,重复调用 getaddrinfo 直到它在网络准备就绪后成功。不幸的是,我发现即使在建立连接后,getaddrinfo 仍会失败并显示 name or service not known

我可以通过主机名 ping 服务器,但 getaddrinfo 仍然无法执行此操作。如果我停止应用程序并再次运行它,一切正常。如果网络连接在第一次调用之前已经建立,getaddrinfo 也可以正常工作。

显然,如果 getaddrinfo 因网络未就绪而失败一次,它将永远失败。它似乎没有意识到现在存在的连接。使用已弃用的 gethostbyname 时,行为是相同的。

这种行为的原因是什么?有没有办法强制 getaddrinfo 刷新内部变量(如果存在)或类似的东西,这可以解释为什么函数仍然认为没有连接?为了检查网络是否准备就绪,我应该提前调用另一个函数吗?

我想避免等待一段时间的延迟,期待网络在之后连接。我也更愿意从我的应用程序中检查连接,而不是让 bash 脚本先检查它然后启动应用程序。

最佳答案

您可以通过编译以下测试程序并按照以下说明理解答案:

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
while (1)
{
struct addrinfo *res;
int rc=getaddrinfo(argv[1], "http", NULL, &res);

printf("getaddrinfo returned %d\n", rc);

if (rc == 0)
freeaddrinfo(res);

sleep(1);
}
}

在运行这个测试程序之前:

  1. 连接到网络。
  2. /etc/resolv.conf暂时重命名为/etc/resolv.conf.save
  3. 启动这个测试程序,使用一个好的主机名。
  4. 在测试程序启动并开始打印错误代码后不久,将 /etc/resolv.conf.save 重命名为 /etc/resolv.conf
  5. 观察测试程序仍然报告 DNS 解析失败。
  6. 不过,如果您按 CTRL-C 并重新启动它,测试程序现在将报告有效的 DNS 解析。

当您断开并重新连接网络时,您的网络堆栈会相应地重写和更新 /etc/resolv.conf。 C 库中的 DNS 解析器需要此配置文件。 C库第一次从/etc/resolv.conf中读取DNS配置,并缓存起来。它不会在每次查找时检查 /etc/resolv.conf 的内容是否已更改。

最后:

  1. 你的家庭作业是添加对 resolv.h 中定义的 res_init() 的调用到这个测试程序,阅读相应的手册页,看看会发生什么发生。这就是你的答案。

关于c - 如果 getaddrinfo 失败一次,它将永远失败(即使在网络准备就绪之后),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30360029/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com