stream_set_timeout

(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)

stream_set_timeout设置流上的超时时间

描述

stream_set_timeout(资源 $stream, 整数 $seconds, 整数 $microseconds = 0): 布尔值

设置 stream 上的超时值,以 secondsmicroseconds 的总和表示。

当流超时时,由 stream_get_meta_data() 返回的数组的 'timed_out' 键被设置为 true,虽然不会生成任何错误/警告。

参数

stream

目标流。

seconds

要设置的超时的秒部分。

microseconds

要设置的超时的微秒部分。

返回值

如果成功则返回 true,失败则返回 false

示例

示例 #1 stream_set_timeout() 示例

<?php
$fp
= fsockopen("www.example.com", 80);
if (!
$fp) {
echo
"无法打开\n";
} else {

fwrite($fp, "GET / HTTP/1.0\r\n\r\n");
stream_set_timeout($fp, 2);
$res = fread($fp, 2000);

$info = stream_get_meta_data($fp);
fclose($fp);

if (
$info['timed_out']) {
echo
'连接超时!';
} else {
echo
$res;
}

}
?>

注释

注意:

此函数不适用于 stream_socket_recvfrom() 等高级操作,请改用带有超时参数的 stream_select()

此函数以前称为 set_socket_timeout(),后来又称为 socket_set_timeout(),但这种用法已过时。

参见

添加注释

用户贡献的注释 11 条注释

hamishcool3 at yahoo dot co dot uk
13 年前
如果有人困惑,stream_set_timeout 不适用于使用 socket_create 或 socket_accept 创建的套接字。请改用 socket_set_option。

不要使用
<?php
stream_set_timeout
($socket,$sec,$usec);
?>

请改用
<?php
socket_set_option
($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec'=>$sec, 'usec'=>$usec));
socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array('sec'=>$sec, 'usec'=>$usec));
?>
burninleo at gmx dot net
8 年前
如果超时失败,因为服务器一直保持静默,则可能需要添加 stream_select() 来使超时生效。这可能比非阻塞读取操作效率更高。

<?php
stream_set_timeout
($c, $timeout);
$data = '';
$stR = array($this->smtp_conn);
$stW = null;
while (
is_resource($c) && !feof($c)) {
if (!
stream_select($stR, $stW, $stW, $timeout)) {
trigger_error('Timeout');
break;
}
$str = fgets($c, 515);
$data.= $str;

// 处理“传统”超时
$info = stream_get_meta_data($c);
if (
$info['timed_out']) {
trigger_error('Timeout');
break;
}
}
?>

背景:我们遇到了一个 SMTP 服务器的问题,它在未加密的情况下被寻址,但期望 TLS 加密。仅使用 stream_set_timeout() 无法按预期工作,脚本会挂起一小时或更长时间。
Martin Butt - martin at anti_spambutt.cx
17 年前
以下是一个适用于循环的有效示例

<?php
// 超时时间(秒)
$timeout = 5;

$fp = fsockopen("www.server.com", 80, $errno, $errstr, $timeout);

if (
$fp) {
fwrite($fp, "GET /file.php HTTP/1.0\r\n");
fwrite($fp, "Host: www.server.com\r\n");
fwrite($fp, "Connection: Close\r\n\r\n");

stream_set_blocking($fp, TRUE);
stream_set_timeout($fp,$timeout);
$info = stream_get_meta_data($fp);

while ((!
feof($fp)) && (!$info['timed_out'])) {
$data .= fgets($fp, 4096);
$info = stream_get_meta_data($fp);
ob_flush;
flush();
}

if (
$info['timed_out']) {
echo
"连接超时!";
} else {
echo
$data;
}
}
?>
burninleo at gmx dot net
8 年前
另一个注释已经说明,如果对方响应非常缓慢或根本没有响应,阻塞读取可能会成为问题。在这种情况下,流超时可能无法按预期工作。

但是,php.net 提供的信息很少,说明如何使用非阻塞读取操作。以下是一个代码示例

<?php
stream_set_timeout
($c, $timeout);
$data = '';
while (
is_resource($c) && !feof($c)) {
// 对第一次循环使用非阻塞读取
if (($data === '') and ($timeout > 0)) {
stream_set_blocking($c, false);
$endtimeOut = time() + $timeout;
$str = '';
while ((
time() < $endtimeOut) and (strlen($str) < 515) and !feof($c)) {
sleep(1); // 注意:这可能需要调整
$str.= fgets($c, 515);
}
// 处理首次读取超时
if (time() >= $endtimeOut) {
trigger_error('超时', E_USER_WARNING);
break;
}
stream_set_blocking($c, true);
} else {
$str = fgets($c, 515);
}
$data.= $str;

// 处理“传统”超时
$info = stream_get_meta_data($c);
if (
$info['timed_out']) {
trigger_error('超时', E_USER_WARNING);
break;
}
}
?>
emailfire at gmail dot com
13 年前
当作为 CLI 脚本运行时,此函数似乎没有效果,请参阅 http://bugs.php.net/bug.php?id=36030
ridera
19 年前
我发现需要添加

"stream_set_blocking($fp, FALSE )"

在任何 fgets()、fread() 等之前,以防止代码在调用远程文件并且响应缓慢时挂起。
mildly dull at terriblyclever dot com
14 年前
我对下面的建议没有太多运气(尽管我可能使用错误了它们)。
相反,我使用 stream_context_create() 并为超时设置 http 选项。我将该上下文输入 file_get_contents(),然后就完成了!

对于我下面绝望的朋友:https 传输也可以使用 http 流上下文选项。我还没有验证它是否有效,因为我没有缓慢响应的 ssl 来测试。但是,如果您仍然感到压力,请尝试以下操作(您可能需要修改一下...)。

<?php
$timeout
= 5*60;
$options = array(
'http'=>array(
'method'=>"GET",
'header'=>"Accept-language: en\r\n",
'timeout' => $timeout
)
);
$context = stream_context_create($options);
$contents = file_get_contents($source, false, $context);
?>

是的...这是一个 5 分钟的超时。
alfi_ at yahoo dot com
18 年前
如果您使用 fsockopen() 创建连接,首先要写入流,然后等待回复(例如,使用一些额外的标头模拟 HTTP 请求),那么只有在写入之后才能设置 stream_set_timeout() - 如果在写入之前设置,它对读取超时没有影响 :-(
至少在 PHP/4.3.10 上注意到
rtfm61 at yandex dot ru
18 年前
stream_set_timeout() 不适合 UNIX 设备(/dev/...)等文件,我建议使用 select() 以及所需的超时值 - 这很有效。
Dianoga (dianoga7 [at] 3dgo.net)
17 年前
我发现为了真正阻止套接字使脚本超时,您必须调用 stream_get_meta_data 并检查循环从套接字读取时的超时。

示例

<?php
$sock
= fsockopen($host, 80, $errno, $errstr, 30);
if(!
$sock){
echo
"无法获取服务器状态";
}else{
$out = "GET /server.php HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n\r\n";

fwrite($sock, $out);

stream_set_blocking($fp, FALSE );
stream_set_timeout($sock, $timeout);
$info = stream_get_meta_data($sock);

while (!
feof($sock) && !$info['timed_out']) {
$file .= fgets($sock, 4096);
$info = stream_get_meta_data($sock);
}

fclose($sock);
?>
jack.whoami
10 年前
以防万一有人遇到我的情况... 我试图让微秒部分工作,但它没有按预期工作。

假设阻塞模式为真,我使用

<?php stream_set_timeout($s, 1, 0);?>

我得到了预期的 1 秒延迟。但是当我执行

<?php stream_set_timeout($s, 0, 500);?>

我预计会有 500 微秒的延迟,但我根本没有延迟。但是当我这样做时

<?php stream_set_timeout($s, 0, 500000);?>

我得到了 500 微秒的延迟,这正是我预期的。
To Top