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,選項,應該也可以解決。不過本人沒有嘗試。
以上。

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