libcurl怎样做到限制超时单位为ms

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了libcurl怎样做到限制超时单位为ms相关的知识,希望对你有一定的参考价值。

参考技术A static void cm_perform(struct vmod_curl *c) 


CURL *curl_handle;

CURLcode cr;

struct curl_slist *req_headers = NULL;

struct req_hdr *rh;


char *p;

unsigned u, v;

struct hdr *h, *h2;


curl_handle = curl_easy_init();

AN(curl_handle);


VTAILQ_FOREACH(rh, &c->req_headers, list) 

req_headers = curl_slist_append(req_headers, rh->value);




if (c->method && strcmp(c->method, "POST") == 0) 

curl_easy_setopt(curl_handle, CURLOPT_POST, 1L);

curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, c->postfields);




if (req_headers)

curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, req_headers);

curl_easy_setopt(curl_handle, CURLOPT_URL, c->url);

curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL , 1L);

curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L);

curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, recv_data);

curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, c);

curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, recv_hdrs);

curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, c);


if (c->timeout_ms > 0) 

#ifdef CURL_TIMEOUTMS_WORKS

curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT_MS, c->timeout_ms);

#else

curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, c->timeout_ms / 1000);

#endif




if (c->connect_timeout_ms > 0) 

#ifdef CURL_TIMEOUTMS_WORKS

curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT_MS, c->connect_timeout_ms);

#else

curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, c->connect_timeout_ms / 1000);

#endif




if (c->flags & VC_VERIFY_PEER) 

curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 1L);

 else 

curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);




if (c->flags & VC_VERIFY_HOST) 

curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 1L);

 else 

curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);




if (c->cafile) 

      curl_easy_setopt(curl_handle, CURLOPT_CAINFO, c->cafile);




if (c->capath) 

      curl_easy_setopt(curl_handle, CURLOPT_CAPATH, c->capath);




cr = curl_easy_perform(curl_handle);


if (cr != 0) 

c->error = curl_easy_strerror(cr);




curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &c->status);


VSB_finish(c->body);


if (req_headers)

curl_slist_free_all(req_headers);

cm_clear_req_headers(c);

curl_easy_cleanup(curl_handle);

libcurl多线程超时设置不安全(转)

from http://www.cnblogs.com/kex1n/p/4135263.html

(1), 超时(timeout)

libcurl 是 一个很不错的库,支持http,ftp等很多的协议。使用库最大的心得就是,不仔细看文档,仅仅看着例子就写程序,是一件危险的事情。我的程序崩溃了,我 怀疑是自己代码写的问题,后来发现是库没用对。不仔细看文档(有时候文档本身也比较差劲,这时除了看仔细外,还要多动脑子,考虑它是怎么实现的),后果很 严重。不加思索的使用别人的库或者代码,有时候很惬意,但是出问题时,却是寝食难安的。 

1. CURLcode curl_global_init(long flags); 在多线程应用中,需要在主线程中调用这个函数。这个函数设置libcurl所需的环境。通常情况,如果不显式的调用它,第一次调用 curl_easy_init()时,curl_easy_init 会调用 curl_global_init,在单线程环境下,这不是问题。但是多线程下就不行了,因为curl_global_init不是线程安全的。在多个线 程中调用curl_easy_int,然后如果两个线程同时发现curl_global_init还没有被调用,同时调用 curl_global_init,悲剧就发生了。这种情况发生的概率很小,但可能性是存在的。

2. libcurl 有个很好的特性,它甚至可以控制域名解析的超时。但是在默认情况下,它是使用alarm + siglongjmp 实现的。用alarm在多线程下做超时,本身就几乎不可能。如果只是使用alarm,并不会导致程序崩溃,但是,再加上siglongjmp,就要命了 (程序崩溃的很可怕,core中几乎看不出有用信息),因为其需要一个sigjmp_buf型的全局变量,多线程修改它。(通常情况下,可以每个线程一个 sigjmp_buf 型的变量,这种情况下,多线程中使用 siglongjmp 是没有问题的,但是libcurl只有一个全局变量,所有的线程都会用)。

具体是类似 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L) 的超时设置,导致alarm的使用(估计发生在域名解析阶段),如前所述,这在多线程中是不行的。解决方式是禁用掉alarm这种超时, curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L)。

这样,多线程中使用超时就安全了。但是域名解析就没了超时机制,碰到很慢的域名解析,也很麻烦。文档的建议是 Consider building libcurl with c-ares support to enable asynchronous DNS lookups, which enables nice timeouts for name resolves without signals. c-ares 是异步的 DNS 解决方案。

引自:http://gcoder.blogbus.com/logs/54871550.html

调用libcurl下载,然后使用netstat查看发现有大量的TCP连接保持在CLOSE_WAIT状态
查看libcurl的文档说明,有这样一个选项:

CURLOPT_FORBID_REUSE

Pass a long. Set to 1 to make the next transfer explicitly close the connection when done. Normally, libcurl keeps all connections alive when done with one transfer in case a succeeding one follows that can re-use them. This option should be used with caution and only if you understand what it does. Set to 0 to have libcurl keep the connection open for possible later re-use (default behavior). 

也就是说,默认情况下libcurl完成一个任务以后,出于重用连接的考虑不会马上关闭
如果没有新的TCP请求来重用这个连接,那么只能等到CLOSE_WAIT超时,这个时间默认在7200秒甚至更高,太多的CLOSE_WAIT连接会导致性能问题

解决方法:


curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1); 

最好再修改一下TCP参数调低CLOSE_WAIT和TIME_WAIT的超时时间

以上是关于libcurl怎样做到限制超时单位为ms的主要内容,如果未能解决你的问题,请参考以下文章

libcurl多线程超时设置不安全(转)

asp中session超时怎样写,超时后怎样跳转到指定页面?

怎样看redis 任务队列的任务执行数目

libcurl怎样判断数据接收完成

Oracle使用左外连接时,左表中的一个id在右表(数据表以天为单位)中没有数据 使用nvl替换为0

shell变量定义【学习总结】