libcurl返回DNS无法解析的问题

最近在使用libcurl作为httpclient来获取一些服务时遇到了一个问题,就是在网络切换的时候,执行 curl_easy_perform的时候会报 can’t resolve host 的错误。而且是持续很长时间。但是此时网络环境其实是正常的,使用ping,能够正常地ping通www.baidu.com。应用场景是在一个嵌入式设备上,同时包含有网口和无线,两者接入在不同的网络中。默认以有线优先。但是如果将有线拔掉,切换到无线。调用libcurl服务的进程就会报上述错误。因为设备相当于在家用路由器下面,DNS服务器也就是根路由器,类似于192.168.0.1或者192.168.31.1。考虑从DNS缓存的角度解决问题,查询到curl有CURLOPT_DNS_CACHE_TIMEOUT这个选项,发现了如下一段话,盲猜能解决我的问题。

The name resolve functions of various libc implementations don't re-read name server information unless explicitly told so (for example, by calling res_init(3)). This may cause libcurl to keep using the older server even if DHCP has updated the server info, and this may look like a DNS cache issue to the casual libcurl-app user.

https://curl.haxx.se/libcurl/c/CURLOPT_DNS_CACHE_TIMEOUT.html

个人翻译如下:很多域名解析函数的C库函数是不会重新读取域名服务器的信息的,除非被显式地告知需要如此(像调用res_init)。这会造成libcurl持续使用旧的dns服务器,虽然DHCP已经更新了域名服务器的信息。这对于一个随意的libcurl使用者来说,看起来像是一个DNS缓存问题(orz,说的不就是我嘛)man了一下res_init的定义。

       The  res_init()  function  reads the configuration files (see resolv.conf(5)) to
       get the default domain name, search order and name server  address(es).   If  no
       server  is  given, the local host is tried.  If no domain is given, that associ‐
       ated with the local host is used.  It can be  overridden  with  the  environment
       variable  LOCALDOMAIN.  res_init() is normally executed by the first call to one
       of the other functions.

确实是会读取并刷新存储了DNS服务器和地址的resolv.conf文件来使用。而我这里的场景确实是涉及到网络的切换,导致重新DHCP,此时DNS服务器也发生了变化,原先的DNS服务器也不可访问了。就会导致出现该错误。我采用了如下的比较粗暴的解决方式,测试确认可以解决问题。网络切换后,不会在返回无法解析域名的异常。

    int res =-1 ;
    
    CURL* curl;    
    curl = curl_easy_init();
    ...
    res = curl_easy_perform(curl);
    if (res == CURLE_COULDNT_RESOLVE_HOST){
        res_init();
    }
    

另一种可能也可以解决的办法是为curl句柄设置DNS服务器,使用CURLOPT_DNS_SERVERS,选项,应该也可以解决。不过本人没有尝试。
以上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章