如何在C++中异步执行curl_multi_perform()?

问题描述 投票:0回答:1

我开始使用

curl
同步执行 http 请求。我的问题是如何异步执行?

我做了一些搜索,这使我从这个

问题
和这个示例找到了curl_multi_*界面的文档,但它根本没有解决任何问题。

我的简化代码:

CURLM *curlm;
int handle_count = 0;
curlm = curl_multi_init();

CURL *curl = NULL;
curl = curl_easy_init();

if(curl)
{
    curl_easy_setopt(curl, CURLOPT_URL, "https://stackoverflow.com/");
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
    curl_multi_add_handle(curlm, curl);
    curl_multi_perform(curlm, &handle_count);
}

curl_global_cleanup();

回调方法

writeCallback
不会被调用,也不会发生任何事情。

请告诉我。

编辑:

根据@Remy的下面的答案,我得到了这个,但似乎这并不是我真正需要的。因为使用循环仍然是一种阻塞循环。如果我做错了或者误解了什么,请告诉我。我实际上对 C++ 还很陌生。

这是我的代码:

int main(int argc, const char * argv[])
{
    using namespace std;
    CURLM *curlm;
    int handle_count;
    curlm = curl_multi_init();

    CURL *curl1 = NULL;
    curl1 = curl_easy_init();

    CURL *curl2 = NULL;
    curl2 = curl_easy_init();

    if(curl1 && curl2)
    {
        curl_easy_setopt(curl1, CURLOPT_URL, "https://stackoverflow.com/");
        curl_easy_setopt(curl1, CURLOPT_WRITEFUNCTION, writeCallback);
        curl_multi_add_handle(curlm, curl1);

        curl_easy_setopt(curl2, CURLOPT_URL, "http://google.com/");
        curl_easy_setopt(curl2, CURLOPT_WRITEFUNCTION, writeCallback);
        curl_multi_add_handle(curlm, curl2);

        CURLMcode code;
        while(1)
        {
            code = curl_multi_perform(curlm, &handle_count);

            if(handle_count == 0)
            {
                break;
            }
        }
    }

    curl_global_cleanup();

    cout << "Hello, World!\n";
    return 0;
}

我现在可以同时执行 2 个 http 请求。回调被调用,但仍然需要在执行以下行之前完成。我必须考虑线程吗?

c++ curl asynchronous libcurl
1个回答
10
投票

更仔细地再次阅读文档,特别是这些部分:

https://curl.se/libcurl/c/libcurl-multi.html

您的应用程序可以在需要调用 libcurl 来传输数据时从 libcurl 获取知识,这样您就不必疯狂地忙循环并调用 curl_multi_perform(3)curl_multi_fdset(3) 提供了一个接口,您可以使用该接口从 libcurl 中提取 fd_sets 以在 select() 或 poll() 调用中使用,以便了解何时需要注意多堆栈中的传输。这也使您的程序很容易同时等待您自己的私有文件描述符上的输入,或者如果您愿意的话,可能会不时超时。

https://curl.se/libcurl/c/curl_multi_perform.html

当应用程序发现有可用于 multi_handle 的数据或超时已过时,应用程序应调用此函数来读取/写入现在要读取或写入的任何内容等。curl_multi_perform() 一旦读/写完成。该函数不需要实际有任何数据可供读取或可以写入数据,可以调用它以防万一。它将在第二个参数的整数指针中写入仍在传输数据的句柄数。

如果 running_handles 的数量与上一次调用相比发生了变化(或者小于您添加到多手柄中的简单句柄的数量),您就知道有一个或多个传输正在减少“运行”。然后,您可以调用 curl_multi_info_read(3) 来获取有关每个已完成传输的信息,返回的信息包括 CURLcode 等。如果添加的句柄很快就失败,它可能永远不会被算作 running_handle。

running_handles 在此函数返回时设置为零 (0) 时,不再有任何传输正在进行。

换句话说,您需要运行一个循环来轮询 libcurl 的状态,每当有数据等待传输时调用

curl_multi_perform()
,根据需要重复,直到没有任何数据可以传输。

您链接到的博客文章提到了这个循环:

代码可以这样使用

http http;
http:AddRequest("http://www.google.com");

// 在称为每帧的更新循环中
http:更新();

您没有在代码中执行任何循环,这就是您的回调未被调用的原因。当您拨打

curl_multi_perform()
一次时,尚未收到新数据。

© www.soinside.com 2019 - 2024. All rights reserved.