【问题标题】:Linux c++: getaddrinfo failed with EAI_AGAIN, curl could not resolve hostLinux c++:getaddrinfo 因 EAI_AGAIN 失败,curl 无法解析主机
【发布时间】:2018-04-15 03:03:42
【问题描述】:

我通过 ppp 打开一个 GSM 连接并尝试使用 curl 从 URL 下载文件。

对于少数设备,我从curl 和getaddrinfo 收到 CURLE_COULDNT_RESOLVE_HOST 错误,导致 EAI_AGAIN。

在route 我的ppp0 接口注册正确。 resolv.conf 包含谷歌 DNS 并且在终端中手动执行 nslookup 正在工作。

我不知道为什么它不起作用。我唯一知道的是:IPv6 是不可能的。

这是我的getaddrinfo代码

int checkINet(std::string address)
{
   struct addrinfo hints, *servinfo, *p;
   memset(&hints, 0, sizeof(hints));
   hints.ai_family = AF_INET;
   hints.ai_socktype = SOCK_STREAM;
   char ip_addr[INET6_ADDRSTRLEN];

   int s = getaddrinfo(address.c_str(), NULL, &hints, &servinfo);

   if (s != 0)
   {
      std::cout << "No connection possible: " << address << "\n";
      std::cout << "getaddrinfo: " << s << " " << gai_strerror(s) << "\n";
      return -1;
   }
   else
   {
      std::cout << "Conection successful: " << address << "\n";

      for (p = servinfo; p != NULL; p = p->ai_next)
      {
         void *addr;
         if (p->ai_family == AF_INET)
         {
            struct sockaddr_in *ipv4 =(struct sockaddr_in *)p->ai_addr;
            addr = &(ipv4->sin_addr);
         }
         else
         {
            struct sockaddr_in6 *ipv6 =(struct sockaddr_in6 *)p->ai_addr;
            addr = &(ipv6->sin6_addr);
         }

         inet_ntop(p->ai_family, addr, ip_addr, sizeof ip_addr);
         std::cout << addr << "\n";
      }

   }
   freeaddrinfo(servinfo);
   return 0;
}

对于卷曲:

   CURL *curl;
   FILE *fp;
   CURLcode res;

   // initialise a connection to the server
   curl = curl_easy_init();
   if (curl)
   {
      fp = fopen(UPDATE_ZIP, "wb");
      curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
      curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
      curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
      curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
      curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
      curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
      res = curl_easy_perform(curl);
      curl_easy_cleanup(curl);
      fclose(fp);

      if (CURLE_OK != res)
      {
          std::out << "curl failed with: " << res << "\n";
          return res;
      }
      return 0;
   }
   return -1;

【问题讨论】:

  • nslookup 绕过 NSS 并连接到 DNS 服务器本身。假设 Glibc,getaddrinfo 确实通过 NSS。你能和getent hosts $address的行为和/etc/nsswitch.conf的内容比较吗?
  • 另外,您说 IPv6 是不可能的,所以您将 getaddrinfo() 限制为 IPv4,但您的其余代码正在寻找 IPv6。您是否计划在未来启用 IPv6?此外,您可以将 inet_ntop() 替换为 getnameinfo() 并删除您的 addr 变量:getnameinfo(p-&gt;ai_addr, p-&gt;ai_addrlen, ip_addr, sizeof ip_addr, NULL, 0, NI_NUMERICHOST);
  • IPv6 在我发现之前是剩余的,GSM 提供商只提供 IPv4。我认为 NSS 是我搜索的提示。我会保持更新

标签: c++ linux curl getaddrinfo


【解决方案1】:

短暂的小费是对的。将/etc/nsswitch.con 内的订单从 主机:文件 dns 到 主机:dns 文件

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-12
    • 1970-01-01
    • 2014-09-11
    相关资源
    最近更新 更多