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

时间:2015-05-20 20:44:05

标签: c linux networking archlinux getaddrinfo

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

所以我认为我只会编写一个循环,它会重复调用getaddrinfo,直到网络准备好后才会成功。遗憾的是,即使在建立连接后,我发现getaddrinfo仍与name or service not known失败。

我能够通过主机名ping服务器,但getaddrinfo仍然无法做到。如果我停止应用程序并再次运行它,一切正常。如果在第一次呼叫之前已建立网络连接,getaddrinfo也能正常工作。

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

这种行为的原因是什么?有没有办法强制getaddrinfo刷新内部变量(如果存在)或类似内容,这可能解释为什么函数仍然认为没有连接?是否有其他功能我应该先调用以检查网络是否准备就绪?

我想避免等待一段时间的延迟,期待之后网络连接。我还希望从我的应用程序中检查连接,而不是首先检查bash脚本然后启动应用程序。

1 个答案:

答案 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);
    }
}

在运行此测试程序之前:

  1. 连接到网络。
  2. 暂时重命名/etc/resolv.conf/etc/resolv.conf.save
  3. 使用良好的主机名启动此测试程序。
  4. 测试程序启动后不久,开始打印错误代码,将/etc/resolv.conf.save重命名为/etc/resolv.conf
  5. 观察到测试程序仍在报告DNS解析失败。
  6. 如果您按CTRL-C并重新启动它,测试程序现在将报告有效的DNS解析。
  7. 断开连接并从网络重新连接时,网络堆栈会相应地重写和更新/etc/resolv.conf。 C库中的DNS解析程序需要此配置文件。 C库第一次从/etc/resolv.conf读取DNS配置并缓存它。对于每次查询,它都不会检查/etc/resolv.conf的内容是否已更改。

    最后:

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