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

kas*_*eia 5 c linux networking archlinux getaddrinfo

我正在编写一个C应用程序,它在启动时作为systemd服务运行(发行版:Arch Linux),并且应该连接到服务器.由于应用程序在引导时运行,因此最终会发生网络连接尚未建立.这自然导致第一个功能失败,需要一个,在我的情况下getaddrinfo.

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

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

显然,如果getaddrinfo由于网络没有准备就失败一次,它将永远失败.似乎没有意识到现有的连接.使用不推荐使用时gethostbyname,行为是相同的.

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

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

Sam*_*hik 7

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

#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);
    }
}
Run Code Online (Sandbox Code Playgroud)

在运行此测试程序之前:

  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,阅读相应的手册页,看看会发生什么。这就是你的答案。