在 PHP 中设置 Curl 的超时

发布于 2024-08-27 14:31:11 字数 620 浏览 6 评论 0原文

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

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

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.

$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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

似最初 2024-09-03 14:31:11

请参阅文档: 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

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

set_time_limit(0);// to infinity for example

See documentation: 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.

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:

set_time_limit(0);// to infinity for example
痴意少年 2024-09-03 14:31:11

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

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

丑丑阿 2024-09-03 14:31:11

这有一个怪癖,可能与某些人相关......来自 PHP 文档注释。

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

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

这对 PHP 开发人员意味着“如果不先测试它,就无法使用此函数,因为您无法判断 libcurl 是否正在使用标准系统名称解析器(但您可以非常确定它是)”< /p>

问题在于,在 (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.";
}

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

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

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:

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

傲性难收 2024-09-03 14:31:11

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

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

鹿港小镇 2024-09-03 14:31:11

您需要确保您和文件之间存在超时。
在本例中是 PHP 和 Curl。

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

curl_setopt($ch, CURLOPT_TIMEOUT, 0);

在 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);

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

回答这个老问题是因为该线程位于 CURL_TIMEOUT 引擎搜索的顶部。

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

To tell Curl to never timeout when a transfer is still active, you need to set CURLOPT_TIMEOUT to 0, instead of 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:

# 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.

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

酒与心事 2024-09-03 14:31:11

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

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

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.

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

最冷一天 2024-09-03 14:31:11

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

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

一腔孤↑勇 2024-09-03 14:31:11

不相关,但请注意 CURLOPT_HTTPHEADER 需要设置一个 HTTP 标头字段数组,格式为 array('Content-type: text/plain', 'Content-length: 100');-)

Not related, but mind that CURLOPT_HTTPHEADER expects an array of HTTP header fields to set, in the format array('Content-type: text/plain', 'Content-length: 100') ;-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文