**目标:**将请求发送到同一URL,而不必等待请求发送函数完成执行。
目前,当我向一个URL发送一个请求时,在使用相同的函数发送另一个请求之前,我必须等待大约10毫秒的服务器响应。这样做的目的是检测网页上的变化比程序当前正在做的稍微快一些,所以WHILE循环以非阻塞的方式运行。
问题:使用libcurl C++时,如果我有一个WHILE循环,它调用一个函数向一个URL发送一个请求,我如何避免在向同一个URL发送另一个请求之前等待该函数完成执行?
注意:我一直在研究libcurl的multi-interface
,但我很难确定这个接口是否更适合对多个URL的并行请求,而不是向同一个URL**发送请求,而不必每次都等待函数完成执行。我尝试了以下方法,并查看了这些资源:
- 尝试使用libcurl请求对C程序进行多线程处理
- How to do curl_multi_perform() asynchronously in C++?
- http://www.godpatterns.com/2011/09/asynchronous-non-blocking-curl-multi.html
- https://curl.se/libcurl/c/multi-single.html
- https://curl.se/libcurl/c/multi-poll.html
下面是我向一个URL发送请求的尝试,但我必须等待request()
函数完成并返回响应代码,然后再发送同一请求。
#include <vector>
#include <iostream>
#include <curl/curl.h>
size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata) {
std::vector<char> *response = reinterpret_cast<std::vector<char> *>(userdata);
response->insert(response->end(), ptr, ptr+nmemb);
return nmemb;
}
long request(CURL *curl, const std::string &url) {
std::vector<char> response;
long response_code;
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
auto res = curl_easy_perform(curl);
// ...
// Print variable "response"
// ...
return response_code;
}
int main() {
curl_global_init(CURL_GLOBAL_ALL);
CURL *curl = curl_easy_init();
while (true) {
// blocking: request() must complete before executing again
long response_code = request(curl, "https://example.com");
// ...
// Some condition breaks loop
}
curl_easy_cleanup(curl);
curl_global_cleanup();
return 0;
}
我已经尽可能地理解了multi-interface
文档,但仍然很难完全理解它/确定它是否真的适合我的特定问题。如果这个问题似乎没有提供足够的我自己的研究,我很抱歉,但我的libcurl知识中有一些空白,我正在努力填补。
如果有人能建议/解释我可以修改上面的单个libcurl示例的方法,使其以非阻塞的方式运行,我将不胜感激。
编辑:
从libcurl的C实现的例子“multi-poll”中,当我运行下面的程序时,URL的内容被打印出来,但是因为它只打印一次,尽管有WHILE (1)
循环,我很困惑它是否向URL发送了重复的非阻塞请求(这是目标),或者只是一个请求,并且正在等待一些其他的变化/事件?
#include <stdio.h>
#include <string.h>
/* somewhat unix-specific */
#include <sys/time.h>
#include <unistd.h>
/* curl stuff */
#include <curl/curl.h>
int main(void)
{
CURL *http_handle;
CURLM *multi_handle;
int still_running = 1; /* keep number of running handles */
curl_global_init(CURL_GLOBAL_DEFAULT);
http_handle = curl_easy_init();
curl_easy_setopt(http_handle, CURLOPT_URL, "https://example.com");
multi_handle = curl_multi_init();
curl_multi_add_handle(multi_handle, http_handle);
while (1) {
CURLMcode mc; /* curl_multi_poll() return code */
int numfds;
/* we start some action by calling perform right away */
mc = curl_multi_perform(multi_handle, &still_running);
if(still_running) {
/* wait for activity, timeout or "nothing" */
mc = curl_multi_poll(multi_handle, NULL, 0, 1000, &numfds);
}
// if(mc != CURLM_OK) {
// fprintf(stderr, "curl_multi_wait() failed, code %d.\n", mc);
// break;
// }
}
curl_multi_remove_handle(multi_handle, http_handle);
curl_easy_cleanup(http_handle);
curl_multi_cleanup(multi_handle);
curl_global_cleanup();
return 0;
}
1条答案
按热度按时间tjrkku2a1#
你需要在while循环中移动curl_multi_add_handle和curl_multi_remove_handle。
当一个传输完成后,简易句柄仍然会添加到〉multi堆栈中。您需要先用curl_multi_remove_handle〉删除简易句柄,然后用curl_easy_cleanup关闭它,或者可能给它设置新的选项,然后用curl_multi_add_handle再次添加〉它,以开始另一个传输。