我正在编写一个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); } }
在运行这个测试程序之前:
/etc/resolv.conf
临时重命名为/etc/resolv.conf.save
。 /etc/resolv.conf.save
重命名为/etc/resolv.conf
。 断开网络并重新连接时,网络堆栈会相应地重写和更新/etc/resolv.conf
。 C库中的DNS解析器需要此配置文件。 C库首次从/etc/resolv.conf
读取DNS配置,并对其进行缓存。 它不检查/etc/resolv.conf
的内容是否发生了变化。
最后:
res_init()
,在resolv.h
定义的测试程序,阅读相应的手册页,看看会发生什么。 这是你的答案。