在尝试连接时取消curl_easy_perform

时间:2015-02-27 14:40:14

标签: c++ c curl libcurl

有没有办法可以在C ++中取消 curl_easy_perform

我有一个场景,我尝试连接到离线的网络资源,curl_easy_perform在返回 CURLE_COULDNT_CONNECT 之前需要一定的时间。 但与此同时,用户已关闭了希望连接的UI,我希望immediatley切断卷曲连接,而不必等待它无法连接。

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

CURL *pEasy = curl_easy_init ();

然后在做curl_easy_perform时我打电话给

curl_easy_cleanup(pEasy);

试图释放或“停止”卷曲连接但是它崩溃了,我从 curl_easy_perform 中收到以下错误:

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

有没有办法可以取消连接尝试???? 我已经阅读了这个链接:How can I immediately cancel a curl operation?但它似乎处理成功连接后取消卷曲连接。

编辑 - 解决方案

我发现如果我打电话:

curl_easy_reset( pEasy );

然后

curlResult = curl_easy_perform ( pEasy );

几乎立即返回结果 CURLE_OPERATION_TIMEDOUT

我认为这就是我所需要的:)

3 个答案:

答案 0 :(得分:1)

您可以事先设置connection timeout,而不是取消尝试。 :

curl_easy_setopt(pEasy, CURLOPT_CONNECTTIMEOUT, 5);

答案 1 :(得分:1)

您可以在一个帖子中运行curl_easy_perform并保留CURL对象。

每当要关闭连接时,在CURL对象上调用curl_easy_setopt(m_chatCurl, CURLOPT_TIMEOUT_MS, 1)

这样连接就会超时,线程就能完成。

答案 2 :(得分:0)

虽然更改超时选项很好,因为它可能只是转发给套接字本身,但我认为最好只是关闭套接字。

>
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-options和读取套接字句柄可能看起来像是危险的操作,因此设置超时也是如此。但是,在读取套接字句柄时,不会修改curl的状态,只读取缓存的套接字,因此我认为它是更安全的选择。

为了安全起见,您可以获取带有回调的套接字并将其存储在一边,因此您可以从另一个线程访问它,而无需完全触摸卷曲句柄。您可以看到这种方法here

当然,关闭插槽并不意味着卷曲的手柄已关闭。 curl句柄仍然存在,您仍然需要确保用curl_easy_cleanup销毁了该句柄-但在确保所有线程都无法通过其connect / send / recv操作失败并留下curl句柄之前,否则无需这样做,否则会有访问冲突的风险。