2017-04-17 135 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预防措施可能是错误的调整。**可能是一个合适的原因,稍后我会试图找出它是否是由于你的描述。我也怀疑是否是由线程竞争条件引起的。 –