【问题标题】:Cancel curl_easy_perform while it is trying to connect尝试连接时取消 curl_easy_perform
【发布时间】:2015-04-30 07:33:54
【问题描述】:

有没有办法在 C++ 中取消 curl_easy_perform??

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

我已尝试存储我使用的 curl 指针:

CURL *pEasy = curl_easy_init ();

然后在它执行 curl_easy_perform 时我调用了

curl_easy_cleanup(pEasy);

试图释放或“停止” curl 连接,但它崩溃了,我从 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

我想这就是我需要的:)

【问题讨论】:

  • 对不起,这个“解决方案”对我来说似乎完全错误......
  • 对于“如何立即取消操作”的问题,这似乎不是一个解决方案。我也在寻找这个问题的直接答案。有的话请告诉我。

标签: c++ c curl libcurl


【解决方案1】:

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

curl_easy_setopt(pEasy, CURLOPT_CONNECTTIMEOUT, 5);

【讨论】:

  • 即使对于 UI 响应来说太长了,如果有多个连接,那么 UI 的设计方式就会一个接一个地连接,因此它的 5xNumConnections
  • @HarryBoy 你不应该在 UI 线程下运行这样的阻塞调用,你会阻塞 UI,或者使用太低的超时,当网络变慢/用户运行时会导致操作失败wifi/用户有间歇性网络问题/等。 - 两者都会惹恼用户。在另一个线程中运行它。
【解决方案2】:

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

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

这样连接将超时,线程将能够完成。

【讨论】:

    【解决方案3】:

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

    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 免受来自套接字操作的错误。当手动关闭socket时,curl_easy_recv之类的操作只会返回错误码,例如:CURLE_RECV_ERROR

    虽然访问 curl-options 和读取套接字句柄可能看起来像一个有风险的操作,但设置超时也是如此。但是,在读取套接字句柄时,不会修改 curl 状态,只读取缓存的套接字,因此我认为它是更安全的选择。

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

    当然,关闭套接字并不意味着卷曲句柄关闭。 curl 句柄仍然存在,您仍然需要确保使用 curl_easy_cleanup 销毁该句柄 - 但在确保所有线程都失败其连接/发送/接收操作并单独保留 curl 句柄之前,不要这样做,否则您将面临风险访问冲突。

    【讨论】:

    • 我不是卷曲专家,但我想大力支持这个解决方案。套接字的东西可能很复杂,这是它的核心。
    猜你喜欢
    • 2017-02-20
    • 1970-01-01
    • 1970-01-01
    • 2012-08-07
    • 2016-07-18
    • 1970-01-01
    • 2020-05-28
    • 2016-05-28
    • 1970-01-01
    相关资源
    最近更新 更多