我正在使用libcurl在C中编写一个小型下载管理器,并遇到了一个有趣的问题。似乎我没有正确理解curl_multi_perform
到目前为止是如何工作的,一旦我发现这个主循环实际上每秒每秒只下载16 KiB:
while (1) {
int cmp_rem;
j_recount_speeds();
j_handle_completed();
j_handle_waiting();
curl_multi_perform(j_curlm, &cmp_rem);
j_status();
sleep(1);
}
我查看了涉及多接口的一些examples on cURL's website,并发现正确的方法是在套接字文件描述符上select
,一旦准备就回忆curl_multi_perform
。
我希望能够定期运行j_recount_speeds
,j_handle_completed
,j_handle_waiting
和j_status
。我可以在一个主循环中执行此操作以及我需要对curl_multi_perform
执行的操作,还是需要使用单独的线程?
答案 0 :(得分:1)
您不需要单独的线程,您只需要了解可用的接口。首先,您可以发出带超时的select():
while (continue_condition_true) {
struct timeval tv = { 1, 0 }; /* 1 second, zero microseconds */
/* Select returns 0 if it has timed out */
if (select(nfds, readfds, writefds, exceptfds, &tv) == 0) {
/* perform timeout operations here */
continue;
}
}
请注意,这需要对select()的返回值进行真正的错误检查;这段代码仅供寓教于乐!
其次,您可以使用gettimeofday()来检查已用时间:
struct timeval base_tv, tmp_tv;
gettimeofday(&base_tv, NULL);
/* do your processing here */
gettimeofday(&tmp_tv, NULL);
if (tmp_tv.tv_sec - base_tv.tv_sec > 0) {
/* perform timeout operations here */
/* update base_tv to new 'base' time */
gettimeofday(&base_tv, NULL);
}
当然,这只是一个课程超时(并且忽略了比较中的微秒),但是为了更新cURL,用户的显示应该是足够的。
编辑:
根据文档,从CURLM结构中提取fdset信息会出现:
fd_set readfds, writefds, exceptfds;
struct timeout tv = { 1, 0 }; /* 1-second timeout */
int nfds;
/* extract fd_set data from CURLM data */
curl_multi_fdset(curlm, &readfds, &writefds, &exceptfds, &nfds);
select(nfds, &readfds, &writefds, &exceptfds, &tv);
同样,仅对于寓教于乐,真正的错误处理代码需要进入此处,纳尼亚的保修无效等等。