5

我已经阅读并深刻理解了这些: http ://www.php.net/manual/en/features.connection-handling.php http://www.php.net/manual/en/function.register-shutdown-function .php

但是,我已经测试了 PHP 5.1.6 和 5.3,但事情并没有像那里描述的那样工作。我观察到的是:

  • connection_status() 始终返回 true,即使在客户端关闭连接之后也是如此。
  • 即使ignore_user_abort为0,客户端关闭连接后脚本的执行仍会继续
  • 在脚本结束之前,使用 register_shutdown_function() 注册的函数不会运行。当客户端中止连接时,脚本不会被中断(因此函数不会被调用)。

所以基本上 PHP 根本不会检测到客户端的断开连接。

请注意,这并不是将 ignore_user_abort 设置为 1:如果是这种情况,则 connection_status() 将返回 1,即使脚本将继续运行并且直到结束才会调用关闭函数。事实并非如此。

ini_get("ignore_user_abort") 按预期返回 0。

这是 PHP 中的错误,还是由于某些 Apache 设置?

如何让 PHP 按照上述文档中的描述工作?

测试脚本:

<?php

function myShutdown() {
    error_log("myShutdown ".connection_status()." ".ini_get("ignore_user_abort"));
}

register_shutdown_function(myShutdown);

echo "Hi!";
error_log(" *** test/test *** ");
for ($i=0; $i<10; $i++) {
    sleep(1);
    error_log(".");
    echo ".";
}
?>

重现步骤: - 访问脚本的 url - 在 10 秒过去之前中止客户端上的连接(例如点击浏览器中的停止按钮)

预期/期望的行为:日志应显示少于 10 个点,并在末尾显示“myShutdown 1 0”(如果您实时查看日志,则 myShutDown 应在客户端断开连接时立即出现)

观察到的/当前的行为:日志总是显示正好 10 个点,最后显示“myShutdown 0 0”(如果您实时观看,无论客户端何时断开连接,它都会持续 10 秒)。

4

1 回答 1

5

首先,使用基本的 ubuntu 12.04 LAMP 安装(php5.3),我也无法让它工作。但是我有一些信息,希望对您有所帮助。任何意见或编辑表示赞赏!:)


我发现您的代码存在两个问题。第一个是语法错误。myShutdown调用时缺少单引号register_shutdown_function()。将行更改为:

register_shutdown_function('myShutdown');

我看到的第二个问题是sflush()之后丢失的调用echo。文档说:

在尝试向客户端发送信息之前,PHP 不会检测到用户已中止连接。简单地使用 echo 语句并不能保证发送信息,请参见 flush()。

但即使flush()在任何情况下都无济于事。从以下文档flush()

flush() 可能无法覆盖 Web 服务器的缓冲方案,并且它对浏览器中的任何客户端缓冲都没有影响。它也不会影响 PHP 的用户空间输出缓冲机制。这意味着如果您正在使用 ob_flush() 和 flush() 来刷新 ob 输出缓冲区,则必须调用它们。

一些服务器,特别是在 Win32 上,仍然会缓冲脚本的输出,直到它在将结果传输到浏览器之前终止。

Apache 的服务器模块(如 mod_gzip)可能会自己进行缓冲,这将导致 flush() 不会导致数据立即发送到客户端。

甚至浏览器也可以在显示之前缓冲它的输入。例如,Netscape 会缓冲文本,直到它接收到行尾或标记的开头,并且在看到最外层表格的标记之前不会呈现表格。

某些版本的 Microsoft Internet Explorer 仅在收到 256 字节的输出后才开始显示页面,因此您可能需要在刷新之前发送额外的空格以使这些浏览器显示页面。

在该页面的评论中,建议设置几个标头和 apache 配置:

apache_setenv('no-gzip', 1); 
ini_set('zlib.output_compression', 0); 
ini_set('implicit_flush', 1); 

但是,即使这对我也不起作用。我已经使用wiresharek对此进行了调查,尽管Web服务器在0.0037秒后发送内容('Hi'),但Web浏览器正在缓冲页面。

于 2013-04-13T20:37:45.133 回答