在 PHP 中设置 Curl 的超时

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2582057/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 07:00:34  来源:igfitidea点击:

Setting Curl's Timeout in PHP

phphttpcurltimeout

提问by Moki

I'm running a curl request on an eXist database through php. The dataset is very large, and as a result, the database consistently takes a long amount of time to return an XML response. To fix that, we set up a curl request, with what is supposed to be a long timeout.

我正在通过 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);

However, the curl request consistently ends before the request is completed (<1000 when requested via a browser). Does anyone know if this is the proper way to set timeouts in curl?

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

回答by msangel

See documentation: http://www.php.net/manual/en/function.curl-setopt.php

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

CURLOPT_CONNECTTIMEOUT- The number of seconds to wait while trying to connect. Use 0 to wait indefinitely.
CURLOPT_TIMEOUT- The maximum number of seconds to allow cURL functions to execute.

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

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); 
curl_setopt($ch, CURLOPT_TIMEOUT, 400); //timeout in seconds

also don't forget to enlarge time execution of php script self:

也不要忘记扩大php脚本自身的执行时间:

set_time_limit(0);// to infinity for example

回答by Chad Birch

Hmm, it looks to me like CURLOPT_TIMEOUTdefines the amount of time that any cURL function is allowed to take to execute. I think you should actually be looking at CURLOPT_CONNECTTIMEOUTinstead, since that tells cURL the maximum amount of time to wait for the connection to complete.

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

回答by Simon East

There is a quirk with this that might be relevant for some people... From the PHP docs comments.

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

If you want cURL to timeout in less than one second, you can use CURLOPT_TIMEOUT_MS, although there is a bug/"feature" on "Unix-like systems" that causes libcurl to timeout immediately if the value is < 1000 ms with the error "cURL Error (28): Timeout was reached". The explanation for this behavior is:

"If libcurl is built to use the standard system name resolver, that portion of the transfer will still use full-second resolution for timeouts with a minimum timeout allowed of one second."

What this means to PHP developers is "You can't use this function without testing it first, because you can't tell if libcurl is using the standard system name resolver (but you can be pretty sure it is)"

The problem is that on (Li|U)nix, when libcurl uses the standard name resolver, a SIGALRM is raised during name resolution which libcurl thinks is the timeout alarm.

The solution is to disable signals using CURLOPT_NOSIGNAL. Here's an example script that requests itself causing a 10-second delay so you can test timeouts:

如果您希望 cURL 在不到一秒的时间内超时,您可以使用CURLOPT_TIMEOUT_MS,尽管“类 Unix 系统”上存在一个错误/“功能”,如果值小于 1000 毫秒,则会导致 libcurl 立即超时并出现错误“cURL”错误 (28):已达到超时”。这种行为的解释是:

“如果 libcurl 构建为使用标准系统名称解析器,则传输的该部分仍将使用整秒解析超时,允许的最小超时为一秒。”

这对 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.";
}

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

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

回答by Matt Humphreys

Your code sets the timeout to 1000 seconds. For milliseconds, use CURLOPT_TIMEOUT_MS.

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

回答by MarcoP

You will need to make sure about timeouts between you and the file. In this case PHP and Curl.

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

To tell Curl to never timeout when a transfer is still active, you need to set CURLOPT_TIMEOUTto 0, instead of 1000.

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

curl_setopt($ch, CURLOPT_TIMEOUT, 0);


In PHP, again, you must remove time limits or PHP it self (after 30 seconds by default) will kill the script along Curl's request. This alone should fix your issue.
In addition, if you require data integrity, you could add a layer of security by using ignore_user_abort:

同样,在 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);

A client disconnection will interrupt the execution of the script and possibly damaging data,
eg. non-transitional database query, building a config file, ecc., while in your case it would download a partial file... and you might, or not, care about this.

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

Answering this old question because this thread is at the top on engine searches for CURL_TIMEOUT.

回答这个老问题,因为这个线程在引擎搜索的顶部CURL_TIMEOUT

回答by Brent Baisley

You can't run the request from a browser, it will timeout waiting for the server running the CURL request to respond. The browser is probably timing out in 1-2 minutes, the default network timeout.

您不能从浏览器运行请求,它会超时等待运行 CURL 请求的服务器响应。浏览器可能会在 1-2 分钟后超时,即默认网络超时。

You need to run it from the command line/terminal.

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

回答by wbinky

If you are using PHP as a fastCGI application then make sure you check the fastCGI timeout settings. See: PHP curl put 500 error

如果您使用 PHP 作为 fastCGI 应用程序,请确保检查 fastCGI 超时设置。请参阅:PHP curl put 500 错误