是否有某些情况会导致curl_multi_perform阻塞?

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

有没有什么情况会导致curl_multi_perform被阻塞? 我正在使用curl_multi接口构建https服务,但我们发现curl_multi_perform接口在弱网络条件下会阻塞。 接口内部是否有非异步的调用?造成堵塞。

我想知道一些原因。

asynchronous curl libcurl
1个回答
0
投票

是的,在某些条件下

curl_multi_perform
可以阻止,特别是在弱网络条件下。以下是一些可能的原因:

  1. DNS解析:如果DNS解析时间较长,可能会导致阻塞。默认情况下,cURL 执行同步 DNS 解析,如果 DNS 查找速度慢,可能会阻塞整个过程。您可以通过使用带有异步 DNS 解析的 cURL 来缓解此问题,例如

    c-ares
    或类似的。

  2. SSL/TLS 握手:SSL/TLS 握手过程是通过 HTTPS 建立安全连接所必需的,但可能非常耗时,尤其是在网络连接较弱的情况下。如果花费太长时间,此过程可能会阻塞。

  3. 网络超时和重试:在弱网络条件下,数据包丢失和高延迟可能会导致重复重试和延长超时,这可能会导致

    curl_multi_perform
    出现阻塞。

  4. 阻塞回调:如果使用 cURL 注册的任何回调(如

    write
    read
    progress
    回调)本身执行阻塞操作,它们可能会导致
    curl_multi_perform
    阻塞。

  5. 套接字操作:虽然

    curl_multi_perform
    设计为非阻塞,但底层套接字操作在某些情况下可能会阻塞,特别是在操作系统的网络堆栈或服务器没有响应的情况下。

要解决这些问题,您可以:

  • 使用异步 DNS:使用

    c-ares
    启用异步 DNS。这可以通过构建具有
    c-ares
    支持的 cURL 并使用适当的 cURL 选项来启用它来完成。

  • 调整超时:使用

    CURLOPT_TIMEOUT
    CURLOPT_CONNECTTIMEOUT
    CURLOPT_DNS_SERVERS
    等选项为连接过程的各个阶段设置适当的超时。

  • 使用非阻塞套接字:确保套接字设置为非阻塞模式。 cURL 通常会处理这个问题,但最好仔细检查一下。

  • 监控和调试:使用详细模式 (

    CURLOPT_VERBOSE
    ) 获取 cURL 正在执行的操作的详细日志。这可以帮助您查明阻塞发生的位置。

以下是如何设置其中一些选项的示例:

CURLM *multi_handle;
CURL *easy_handle;

multi_handle = curl_multi_init();
easy_handle = curl_easy_init();

curl_easy_setopt(easy_handle, CURLOPT_URL, "https://example.com");
curl_easy_setopt(easy_handle, CURLOPT_TIMEOUT, 30L);
curl_easy_setopt(easy_handle, CURLOPT_CONNECTTIMEOUT, 10L);
curl_easy_setopt(easy_handle, CURLOPT_VERBOSE, 1L);

curl_multi_add_handle(multi_handle, easy_handle);

int still_running;
do {
    CURLMcode mc = curl_multi_perform(multi_handle, &still_running);

    if (mc == CURLM_OK) {
        int numfds;
        mc = curl_multi_wait(multi_handle, NULL, 0, 1000, &numfds);

        if (mc != CURLM_OK) {
            fprintf(stderr, "curl_multi_wait() failed, code %d.\n", mc);
            break;
        }

        if (!numfds) {
            fprintf(stderr, "No file descriptors ready.\n");
            usleep(100000); // Sleep for a bit to avoid busy-looping
        }
    } else {
        fprintf(stderr, "curl_multi_perform() failed, code %d.\n", mc);
        break;
    }
} while (still_running);

curl_multi_cleanup(multi_handle);
curl_easy_cleanup(easy_handle);

此示例为整个请求和连接阶段设置超时,并使用

curl_multi_wait
有效地等待文件描述符上的活动。调整这些参数可以帮助缓解弱网络条件下的阻塞问题。

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