我正在编写一个C应用程序,它在启动时运行systemd service(发行版:Arch Linux),并且应该连接到服务器。由于应用程序在引导时运行,因此最终会发生网络连接尚未建立。这自然导致第一个函数失败,需要一个函数,在我的例子中是getaddrinfo
。
所以我认为我只会编写一个循环,它会重复调用getaddrinfo
,直到网络准备好后才会成功。遗憾的是,即使在建立连接后,我发现getaddrinfo
仍与name or service not known
失败。
我能够通过主机名ping服务器,但getaddrinfo
仍然无法做到。如果我停止应用程序并再次运行它,一切正常。如果在第一次呼叫之前已建立网络连接,getaddrinfo
也能正常工作。
显然,如果getaddrinfo
由于网络未准备好而失败一次,它将永远失败。似乎没有意识到现有的连接。使用已弃用的gethostbyname
时,行为是相同的。
这种行为的原因是什么?有没有办法强制getaddrinfo
刷新内部变量(如果存在)或类似内容,这可能解释为什么函数仍然认为没有连接?是否有其他功能我应该先调用以检查网络是否准备就绪?
我想避免等待一段时间的延迟,期待之后网络连接。我还希望从我的应用程序中检查连接,而不是首先检查bash脚本然后启动应用程序。
答案 0 :(得分:4)
您可以通过编译以下测试程序并按照以下说明理解答案:
#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
的调用添加到此测试程序,阅读相应的手册页,看看会发生什么。那是你的答案。