2017-04-17 101 views
2

我寫了一個使用libcurl的多線程程序,但有時候curl會抱怨它不能在exec curl_easy_perform後解析主機名,有時候不會。爲什麼libcurl有時會抱怨'無法解析主機名'?

size_t Http::WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) 
{ 
    size_t realsize = size * nmemb; 
    MemoryStruct *mem = (MemoryStruct *)userp; 

    mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1); 
    assert(NULL != mem->memory); 
    memcpy(&(mem->memory[mem->size]), contents, realsize); 
    mem->size += realsize; 
    mem->memory[mem->size] = 0; 

    return realsize; 
} 

void Http::run(const URL &url, Http::FinishedCallback cbk) 
{ 
    CURL *handle = curl_easy_init(); 
    if (handle) 
    { 

     MemoryStruct *chunk = new MemoryStruct; 
     chunk->memory = (char *)malloc(1); /* will be grown as needed by the realloc above */ 
     chunk->size = 0; /* no data at this point */ 


     CURLcode res; 
     curl_easy_setopt(handle, CURLOPT_URL, url.getUrl().c_str()); 
     curl_easy_setopt(handle, CURLOPT_WRITEDATA, (void *)chunk); 
     curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); 
     curl_easy_setopt(handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); 
     curl_easy_setopt(handle, CURLOPT_TIMEOUT, 10L); 
     curl_easy_setopt(handle, CURLOPT_CONNECTTIMEOUT, 10L); 
     res = curl_easy_perform(handle); 

     /* check for errors */ 
     if (CURLE_OK != res) 
     { 
      chunk->status = false; 
      std::string errCode = std::to_string(res); 
      chunk->memory = (char *)realloc(chunk->memory, chunk->size + errCode.size() + 1); 
      memcpy(&(chunk->memory[chunk->size]), errCode.c_str(), errCode.size()); 
      chunk->size += errCode.size(); 
      chunk->memory[chunk->size] = 0; 
     } 
     else 
     { 
      chunk->status = true; 
     } 

#ifdef _DEBUG 
     chunk->url = url; 
#endif 
     cbk(chunk); 
     free(chunk); 
     curl_easy_cleanup(handle); 
    } 
} 


void Http::get(URL url, FinishedCallback cbk) 
{ 
    std::thread http(&Http::run, Http(), url, cbk); 
    http.detach(); 
} 

Http::~Http() 
{ 
    curl_global_cleanup(); 
} 

這是invocer。

int index = 0; 
bool finish = false; 
void func(Http::MemoryStruct *memo) 
{ 
    if (!memo->status) 
    { 
#ifdef _DEBUG 
     LOG(INFO) << "Failure:\t" << curl_easy_strerror((CURLcode)atoi(memo->memory)) << "\n"; 

#endif 
    } 
    else 
    { 
     //LOG(INFO) << memo->memory << '\n'; 
    } 
    finish = memo->status; 
    ++index; 
} 

int main(void) 
{ 
    curl_global_init(CURL_GLOBAL_ALL); 
    URL::AttribMap attribMap{ { "class", "System" }, { "token", "KY0SQ3FX996PU1ZO" }, { "type", "GetConfig" } }; 
    URL url("open.55.la", "/index.php", attribMap); 
    Http http; 
    while(index++ <=10) 
    { 
      try 
      { 
       http.get(url, func); 
      } 
      catch (std::_System_error &err) 
      { 
       LOG(INFO) << err.what(); 
      } 
    } 
    while (true) 
    { 
     ; 
    } 
    el::Loggers::flushAll(); 
    return EXIT_SUCCESS; 
} 

它可以通過數據崩潰造成的呢?

回答

4

這是錯誤消息的libcurl返回了CURLE_COULDNT_RESOLVE_HOST錯誤代碼(6)。

我會引用Exit status section from the curl book

無法解析主機。給定的遠程主機地址不是 已解決。給定服務器的地址無法解析。 給定的主機名稱只是錯誤的,或者DNS服務器是 行爲不當,並且不應該知道這個名字,或者它應該或者可能是 即使您運行的系統捲曲配置錯誤,因此它不會 查找/使用正確的DNS服務器。

如果這是間歇性返回該工作有時有有時沒有主機名,這將表明你有一個破碎的系統不知何故,這並不正確響應或者是某種DOS預防的錯誤調整的DNS服務器。

+1

感謝您的詳細回答,** DNS服務器沒有正確響應,或者某種DOS預防措施可能是錯誤的調整。**可能是一個合適的原因,稍後我會試圖找出它是否是由於你的描述。我也懷疑是否是由線程競爭條件引起的。 –