尝试连接时取消curl_easy_perform

Cancel curl_easy_perform while it is trying to connect

本文关键字:easy perform curl 取消 连接      更新时间:2023-10-16

有没有办法取消C++中的curl_easy_performance??

我有一个场景,我试图连接到脱机的网络资源,curl_easy_perform需要一定的时间才能返回CURLE_COULDNT_connect。但与此同时,用户已经关闭了希望连接的UI,我想立即切断curl连接,而不必等待它无法连接。

我已经尝试存储我使用的卷曲指针:

CURL *pEasy = curl_easy_init ();

然后当它执行curl_easy_perform时,我打电话给

curl_easy_cleanup(pEasy);

在试图释放或"停止"卷曲连接时,它崩溃了,我从curl_easy_performance得到了以下错误:

Unhandled exception at blah blah: Access violation reading location 0x00000004.

有没有办法取消连接尝试????我读过这个链接:如何立即取消卷曲手术?但它似乎可以在成功连接后取消卷曲连接。

编辑-解决方案

我发现,如果我打电话:

curl_easy_reset( pEasy );

然后

curlResult = curl_easy_perform ( pEasy );

几乎立即返回结果CURLE_OPERATION_TIMEDOUT

我想这就是我需要的:)

您可以在线程中运行curl_easy_perform并保留CURL对象。

在CURL对象上,只要您想关闭连接,就调用curl_easy_setopt(m_chatCurl, CURLOPT_TIMEOUT_MS, 1)

通过这种方式,连接将超时,线程将能够完成。

您可以预先设置连接超时,而不是取消尝试,例如:

curl_easy_setopt(pEasy, CURLOPT_CONNECTTIMEOUT, 5);

虽然更改超时选项很可能很好,因为它可能

void terminateConnectionNow(CURL* curlHandle)
{
    curl_socket_t sockfd;
    auto res = curl_easy_getinfo(curlHandle, CURLINFO_ACTIVESOCKET, &sockfd);
    // ASSERT_EQ(res, CURLE_OK); - no point in doing anything if the socket is not there
    closesocket(sockfd);
}

关闭插座可以确保连接完全断开,无论它在哪里连接、发送、接收等,因此在最后一刻都没有连接的机会。

curl_easy_cleanup相反,即使从另一个线程执行该操作,curl也不会崩溃——sockets本身由操作系统管理,因此关闭套接字是线程安全的。然后,curl可以适当地防御套接字操作带来的错误。当手动关闭套接字时,像curl_easy_recv这样的操作只会返回错误代码,例如:CURLE_RECV_ERROR

虽然访问curl选项和读取套接字句柄看起来可能是一个有风险的操作,但设置超时也是如此。然而,当读取套接字句柄时,curl状态不会被修改,只读取缓存的套接字,所以我认为这是一个更安全的选项。

为了完全安全,您可以通过回调获得套接字并将其存储在一边,这样您就可以从另一个线程访问它,而无需接触curl句柄。你可以在这里看到这种方法。

当然,关闭插座并不意味着卷曲手柄关闭。curl句柄仍然有效,您仍然需要确保使用curl_easy_cleanup销毁该句柄,但在确保所有线程的connect/send/recv操作失败并保留curl句柄之前,否则您将面临访问冲突的风险。