【问题标题】:libcurl: how does connection Keep-Alive work?libcurl:连接 Keep-Alive 是如何工作的?
【发布时间】:2020-02-09 21:45:57
【问题描述】:

如何保持与 libcurl 的连接?

我想要的用法如下。我想连接到支持Keep-Alive 但在 90 秒不活动后关闭连接的服务器。当某些事件(此连接之外)发生时,我想偶尔执行POST,并且我想保持连接处于活动状态以减少延迟。可能会超过 90 秒没有事件发生,所以我想要一种方法来告诉服务器我没有空闲。

示例页面非常好,但我没有看到涉及Keep-Alivehttps://curl.haxx.se/libcurl/c/example.html

我确实找到了CURLOPT_TCP_KEEPINTVL:https://curl.haxx.se/libcurl/c/CURLOPT_TCP_KEEPINTVL.html,但我不清楚它应该如何工作。在那个例子中,我们看到了代码:

CURL *curl = curl_easy_init();
if(curl) {
  curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");

  /* enable TCP keep-alive for this transfer */
  curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);

  /* set keep-alive idle time to 120 seconds */
  curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);

  /* interval time between keep-alive probes: 60 seconds */
  curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L);

  curl_easy_perform(curl);
}

描述如下:

长传。设置操作系统在发送 keepalive 探测之间等待的时间间隔(以秒为单位)。并非所有操作系统都支持此选项。 (在 7.25.0 中添加)

两个问题:

A) 在操作上,我该如何使用它?从描述来看,只要我将curl 保留在范围内,连接就会保持打开状态。它是否正确?然后我应该继续做吗

curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postthis);
res = curl_easy_perform(curl);

每当我想POST 更多数据时,它将在同一个连接中发送,还是有更多数据?

B) 这些 keepalive 探针是什么?我在哪里可以了解更多关于它们的信息?这是操作系统在我背后做的事情吗?我是否应该将其视为:从我的应用程序的角度来看,连接神奇地活着,我不应该担心它?


是的,我的意思是 HTTP Keep-Alive,对于歧义,抱歉。

从昨天开始,我发现 Daniel Stenberg 本人在这里回答了类似的问题:https://stackoverflow.com/a/14148171/12874900

这回答了我问题的 A) 部分。但它没有回答问题 B)。我还需要知道:如果连接因某种原因而中断,我该如何检测它?还是 libcurl 负责重新连接?

有人可以随意将其编辑到我的原始帖子中。

【问题讨论】:

  • 它应该默认发生,因为它从 HTTP 1.1 开始默认启用。
  • @cyalin 你说的是 TCP 连接保活还是 HTTP 保活?
  • @MarcoBonelli 阅读标题和问题。当阅读为关于 TCP keepalive 时,这个问题没有任何意义。它提到了“connection keepalive”,这实际上是相关 HTTP 标头的名称,以及服务器保持连接打开的时间,这是 HTTP keepalive 所做的。
  • @user207421 向我建议 HTTP 保持活动状态的唯一事实是它提到了 POST 请求。假设我将立即删除答案并在需要时取消删除,这听起来是一个更好的主意。你很可能是对的,这是我的错。
  • TCP keep-alive 与 HTTP keep-alive 无关。除非我认为您的服务器允许保持连接打开数小时。

标签: c http libcurl


【解决方案1】:

HTTP 持久连接

正如多次所说:libcurl 默认情况下会进行持久的 HTTP 连接。你只需要重用 curl 句柄就可以了,如果你不想要它们,你必须主动要求 not 持久化它们。使用什么 HTTP 方法并不重要。 GET、POST、HEAD 等都保持连接 - 除非发生异常情况。

然而,现代 libcurl 版本只能重用连接 CURLOPT_MAXAGE_CONN 秒(默认为 118) - 因为随着时间的推移,成功重用的机会会迅速减少。

有时您会看到客户端使用 Keep-Alive: 标头,但这是 HTTP/1.0 时代的遗留问题,在当今时代几乎毫无意义。

如果此问题中声称的连接在 90 秒后关闭,那是因为服务器随后关闭了空闲连接。服务器这样做。除了在服务器终止连接之前再次使用连接之外,您无法以任何其他方式阻止它们。

TCP 保活

TCP keepalive 选项处于完全不同的级别。这基本上是 TCP 在 N 秒不活动后通过连接发送数据包,以确保连接保持活动状态(并检测断开的连接)。

libcurl 默认不启用 TCP keepalive,见CURLOPT_TCP_KEEPALIVE

【讨论】:

  • 有没有办法调试 TCP 级别的keepalive 的使用?我正在尝试通过-v 以及httpbin.org/delay/3 上的--trace - 并希望在调试输出中看到something,但是无论是否指定--keepalive-time 1,输出看起来都完全相同(即没有发送保活探测的指示)。示例:curl --keepalive-time 1 https://httpbin.org/delay/3 -v
  • (偏离原始问题)TCP keepalive 由 TCP 堆栈完成,curl 无法显示它们。我建议使用 Wireshark 来窥探和分析流量。
  • 你可以使用 tcpdump 来检查 keepalives
  • 如果libcurl尝试重用一个HTTP Keep-alive连接,发现服务器已经断开连接(如上例中的90s超时)。此时,libcurl 会向调用者报告错误还是会悄悄地尝试在当前句柄上创建新的 HTTP 连接并重试请求?
  • 然后 libcurl 将创建一个新连接并使用它
猜你喜欢
  • 1970-01-01
  • 2015-05-30
  • 1970-01-01
  • 2012-05-09
  • 2017-02-19
  • 1970-01-01
  • 2014-06-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多