如果getaddrinfo一旦失败就会失败(即使networking准备就绪后)

我正在编写一个C应用程序,它在启动时作为systemd服务运行(distro:Arch Linux),并且应该连接到服务器。 由于应用程序在启动时运行,最终发生networking连接尚未build立。 这自然会导致第一个函数失败,需要一个,在我的情况下是getaddrinfo

所以我认为我只是写一个循环,反复调用getaddrinfo直到networking准备就绪。 不幸的是,我发现getaddrinfo在连接build立之后name or service not known

我能够通过其主机名ping服务器,但getaddrinfo仍然不会这样做。 如果我停止应用程序并再次运行,一切正常。 如果networking连接在第一次调用之前已经build立, getaddrinfo可以正常工作。

显然,如果getaddrinfo失败一次,因为networking没有准备好,它将永远失败。 似乎没有意识到现在的联系。 使用不推荐的gethostbyname ,行为是相同的。

这种行为的原因是什么? 有没有办法强制getaddrinfo刷新内部variables(如果存在)或类似的这可能解释为什么该函数仍然认为没有连接? 是否有另一个function,我应该以前调用,以检查networking是否准备好了?

我想避免等待一段时间,期待networking连接后。 我也希望检查从我的应用程序的连接,并没有一个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. 你的家庭作业是添加一个调用res_init() ,在resolv.h定义的测试程序,阅读相应的手册页,看看会发生什么。 这是你的答案。