在一个主循环中显示状态并执行下载

时间:2012-02-23 09:21:50

标签: c libcurl

我正在使用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_speedsj_handle_completedj_handle_waitingj_status。我可以在一个主循环中执行此操作以及我需要对curl_multi_perform执行的操作,还是需要使用单独的线程?

1 个答案:

答案 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);

同样,仅对于寓教于乐,真正的错误处理代码需要进入此处,纳尼亚的保修无效等等。