PHP cURL:CURLOPT_CONNECTTIMEOUT 与 CURLOPT_TIMEOUT

Posted

技术标签:

【中文标题】PHP cURL:CURLOPT_CONNECTTIMEOUT 与 CURLOPT_TIMEOUT【英文标题】:PHP cURL: CURLOPT_CONNECTTIMEOUT vs CURLOPT_TIMEOUT 【发布时间】:2015-03-02 18:57:46 【问题描述】:

php 有这两个与超时相关的选项:CURLOPT_CONNECTTIMEOUTCURLOPT_TIMEOUT

PHP 网站上的描述有点模糊。有什么区别?

举一个现实世界的例子:假设您通过 cURL 将 GET vars 发送到一个 URL,并且您希望接收一个 XML 返回,CURLOPT_CONNECTTIMEOUT 是否与连接到服务器所需的最长时间有关和CURLOPT_TIMEOUT 发送回 XML 所需的最长时间?

【问题讨论】:

还有 CURLOPT_TIMEOUT_MS。我不确定当同时定义 CURLOPT_TIMEOUT_MS 和 CURLOPT_TIMEOUT 时会发生什么。我想应该定义两者中的任何一个。 @SandeepanNath 来自CURL docs for CURLOPT_TIMEOUT,它指出,“如果同时设置了 CURLOPT_TIMEOUT 和 CURLOPT_TIMEOUT_MS,则将使用最后设置的值。” 【参考方案1】:

接受的答案不正确。有关正确的文档,请参阅 Everything CURL 文档。

连接时间基本上涵盖了建立http连接的两个方面:

DNS 解析 tcp 连接建立之前的时间。

CURLOPT_TIMEOUT 或 CURLOPT_TIMEOUT_MS 选项根本没有涵盖这段时间。这些涵盖了在我们开始通过刚刚在连接阶段建立的 TCP 连接上的 HTTP 之后发生的所有事情。

这种区别给很多人带来了问题,但它确实允许设置一个相对较短的连接超时,因为如果服务器完全不可用,为什么还要等待呢?但是,如果服务的预期响应时间难以预测,您仍然可以将请求超时设置为相当长的时间。

一般来说,对于生产设置,CURLOPT_CONNECTION_TIMEOUT 应小于 5 秒,CURLOPT_TIMEOUT 应尽可能低(不会导致您经常丢弃请求)。

【讨论】:

【参考方案2】:

CURLOPT_CONNECTTIMEOUT 是仅连接到服务器的时间。

CURLOPT_TIMEOUT 是整个连接时间加上交换数据的时间。

因此,CURLOPT_TIMEOUT 始终包含 CURLOPT_CONNECTTIMEOUT。

使用 CURLINFO_CONNECT_TIME 和 CURLINFO_TOTAL_TIME 验证是否非常容易。

curl_getinfo($ch, CURLINFO_CONNECT_TIME) 获取信息,curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $yourMaxConnTime) 设置要连接的最大值。

curl_getinfo($ch, CURLINFO_TOTAL_TIME) 获取信息,curl_setopt($ch, CURLOPT_TIMEOUT, $yourMaxTotTime) 设置整个操作的最大值。

当然,$yourMaxTotTime 必须始终高于 $yourMaxConnTime。 所有这些值都以秒为单位。

【讨论】:

【参考方案3】:

除了accepted answer。

根据source code 设置已连接:如果两者都设置,则使用最严格的设置。但仅限于连接阶段。

/* if a timeout is set, use the most restrictive one */

  if(data->set.timeout > 0)
    timeout_set |= 1;
  if(duringconnect && (data->set.connecttimeout > 0))
    timeout_set |= 2;

  switch(timeout_set) 
  //...
  case 3:
    if(data->set.timeout < data->set.connecttimeout)
      timeout_ms = data->set.timeout;
    else
      timeout_ms = data->set.connecttimeout;
    break;

Unit tests 表示来源

【讨论】:

【参考方案4】:

CURLOPT_CONNECTTIMEOUT 不是由 CURLOPT_TIMEOUT 表示的时间段

如果 CURLOPT_CONNECTTIMEOUT 设置为 3 秒,CURLOPT_TIMEOUT 设置为 4 秒,则执行最多可能需要 7 秒。

我通过模拟慢速服务器连接(iptables drop)对此进行了测试。

【讨论】:

我想我可以确认一下。我已将CURLOPT_TIMEOUT 配置为4 并保持CURLOPT_CONNECTTIMEOUT 不变。我还为超过 10 秒的请求配置了 PHP 慢日志。我的 PHP 脚本连接到远程站点,并且慢速日志经常报告 curl_exec() 花费超过 10 秒的问题。我会假设它仅限于手册中的4 你看过这个comment 吗? 根据我在源代码中阅读的内容,这是不正确的,但是如果您通过实验验证它,那将表明不同版本中存在不同的实现......然而GitHub上的版本并没有12 年改变了这个功能。【参考方案5】:

CURLOPT_CONNECTTIMEOUT 是允许与服务器建立连接的最长时间(以秒为单位)。 可以将其设置为 0 以禁用此限制,但在生产环境中不建议这样做。

CURLOPT_TIMEOUT 是单个 cURL 扩展函数调用的执行将被限制的最长时间(以秒为单位)。 请注意,此设置的值应包括 CURLOPT_CONNECTTIMEOUT 的值。

换句话说, CURLOPT_CONNECTTIMEOUT是CURLOPT_TIMEOUT所代表的时间段,所以CURLOPT_TIMEOUT的值应该大于CURLOPT_CONNECTTIMEOUT的值。

来自Difference between CURLOPT_CONNECTTIMEOUT and CURLOPT_TIMEOUT

【讨论】:

我想说,这并不正确。 Here 它说,CURLOPT_TIMEOUT 定义了“您允许 libcurl 传输操作花费的最长时间(以秒为单位)。”。这有点模棱两可。我的经验似乎证实了 Miloš 在下面的回答:CURLOPT_CONNECTTIMEOUT 实际上只适用于连接阶段CURLOPT_TIMEOUT 是适用于传输阶段。两者都添加了定义curl_exec()的完整超时。 为了说明这一点,让我补充一下这个解释。 CURL_CONNECTIONTIMEOUT 是您已经连接时可以保留连接的最长时间。而 CURL_TIMEOUT 是无法建立连接时您可以从开始到结束尝试的最长时间。 -1,使用的来源是一个不正确的非权威博客,如那里自己的cmets和这里的其他答案所示 如前所述,CURL_CONNECTIONTIMEOUT 是连接阶段,CURLOPT_TIMEOUT 是从最终连接到数据传输结束的一切。常见的方法可能是每次尝试失败时逐渐增加连接超时,但将传输超时保持较高,以免等待无效连接的时间过长 我扫描了 CURL 源代码以确定,它似乎证实了这个答案。如果只设置了 CURLOPT_CONNECTTIMEOUT,那么只有连接阶段会受到它的影响。如果只设置了 CURLOPT_TIMEOUT,那么它适用于整个 curl 操作,包括连接。但是,如果两者都设置,则连接阶段使用两个超时中较短的一个。见curl/lib/connect.c中的函数Curl_timeleft()

以上是关于PHP cURL:CURLOPT_CONNECTTIMEOUT 与 CURLOPT_TIMEOUT的主要内容,如果未能解决你的问题,请参考以下文章

linux上怎么操作开启php curl扩展

PHP如何开启curl

PHP - curl实现采集

php curl 302问题

php curl get 参数

php curl_exec无法返回结果