在PHP中设置Curl的超时

Mok*_*oki 212 php curl timeout http

我正在通过php在eXist数据库上运行curl请求.数据集非常大,因此,数据库一直需要很长时间才能返回XML响应.为了解决这个问题,我们设置了一个curl请求,它应该是一个长时间的超时.

$ch = curl_init();
$headers["Content-Length"] = strlen($postString);
$headers["User-Agent"] = "Curl/1.0";

curl_setopt($ch, CURLOPT_URL, $requestUrl);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, 'admin:');
curl_setopt($ch,CURLOPT_TIMEOUT,1000);
$response = curl_exec($ch);
curl_close($ch);
Run Code Online (Sandbox Code Playgroud)

但是,卷曲请求始终在请求完成之前结束(通过浏览器请求时<1000).有谁知道这是否是在卷曲中设置超时的正确方法?

msa*_*gel 321

参见文档:http://www.php.net/manual/en/function.curl-setopt.php

CURLOPT_CONNECTTIMEOUT - 尝试连接时等待的秒数.使用0无限期等待.
CURLOPT_TIMEOUT - 允许cURL函数执行的最大秒数.

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); 
curl_setopt($ch, CURLOPT_TIMEOUT, 400); //timeout in seconds
Run Code Online (Sandbox Code Playgroud)

也不要忘记放大时间执行php脚本自我:

set_time_limit(0);// to infinity for example
Run Code Online (Sandbox Code Playgroud)

  • 如果脚本在控制台上运行,则不需要`set_time_limit(0);` (12认同)
  • CURLOPT_CONNECTTIMEOUT = 0 并不意味着“无限期” https://curl.se/libcurl/c/CURLOPT_CONNECTTIMEOUT.html “设置为零以切换到默认的内置连接超时 - 300 秒。” (5认同)
  • @PedroLobito你提到的是cli上php的默认配置,但有可能这已被修改. (4认同)
  • @cherouvim在这里显然是正确的(只需运行`php -d max_execution_time = 1 -r'while(true){$ r = 1*1;}'或者在行动中观察cli没有魔法的东西'总是无限的'旗帜. (3认同)

Cha*_*rch 57

嗯,在我看来,它CURLOPT_TIMEOUT定义了允许任何cURL函数执行的时间量.我认为你应该实际上看一下CURLOPT_CONNECTTIMEOUT,因为它告诉cURL等待连接完成的最长时间.


Sim*_*ast 30

这有一个怪癖可能与某些人有关......来自PHP文档的评论.

如果你想卷曲在不到一秒钟的超时时间,你可以使用CURLOPT_TIMEOUT_MS,虽然对"类Unix系统"的错误/"特性"导致的libcurl与错误"卷曲立即超时如果值为<1000毫秒错误(28):达到超时".这种行为的解释是:

"如果libcurl构建为使用标准系统名称解析器,那么传输的那部分仍将使用全秒分辨率进行超时,允许的最小超时时间为1秒."

这意味着到PHP开发人员是"没有首先测试它无法使用此功能,因为你不能告诉我们,如果libcurl的是使用标准的系统名称解析(但可以肯定它是)"

问题是在(Li | U)nix上,当libcurl使用标准名称解析器时,在名称解析期间会引发SIGALRM,而libcurl认为这是超时警报.

解决方案是使用CURLOPT_NOSIGNAL禁用信号.这是一个示例脚本,它请求自身导致10秒延迟,以便您可以测试超时:

if (!isset($_GET['foo'])) {
    // Client
    $ch = curl_init('http://localhost/test/test_timeout.php?foo=bar');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200);
    $data = curl_exec($ch);
    $curl_errno = curl_errno($ch);
    $curl_error = curl_error($ch);
    curl_close($ch);

    if ($curl_errno > 0) {
        echo "cURL Error ($curl_errno): $curl_error\n";
    } else {
        echo "Data received: $data\n";
    }
} else {
    // Server
    sleep(10);
    echo "Done.";
}
Run Code Online (Sandbox Code Playgroud)

来自http://www.php.net/manual/en/function.curl-setopt.php#104597


小智 27

您的代码将超时设置为1000 .毫秒,请使用CURLOPT_TIMEOUT_MS.


Mar*_*coP 11

您需要确保您和文件之间的超时.在这种情况下PHP和Curl.

要告诉Curl在传输仍处于活动状态时永不超时,您需要设置CURLOPT_TIMEOUT0,而不是1000.

curl_setopt($ch, CURLOPT_TIMEOUT, 0);
Run Code Online (Sandbox Code Playgroud)

在PHP中,您必须再次删除时间限制或PHP自身(默认情况下30秒后)将沿着Curl的请求终止脚本.仅这一点就可以解决您的问题.
此外,如果您需要数据完整性,可以使用以下命令添加一层安全性ignore_user_abort:

# The maximum execution time, in seconds. If set to zero, no time limit is imposed.
set_time_limit(0);

# Make sure to keep alive the script when a client disconnect.
ignore_user_abort(true);
Run Code Online (Sandbox Code Playgroud)

客户端断开连接将中断脚本的执行并可能破坏数据,
例如.非过渡数据库查询,构建配置文件,ecc.,而在您的情况下,它将下载一个部分文件...你可能或不关心这一点.

回答这个老问题,因为这个帖子在引擎搜索时位于顶部CURL_TIMEOUT.


Bre*_*ley 8

您无法从浏览器运行请求,它将超时等待运行CURL请求的服务器响应.浏览器可能会在1-2分钟内超时,默认网络超时.

您需要从命令行/终端运行它.

  • +1 - 超时可能是卷曲的外部.实际上,您可以通过确保定期输出内容来解决浏览器超时问题.浏览器通常会在每次收到更多数据时重置其超时.但这是一个黑客; 通过CLI运行(几乎?)始终是首选. (2认同)