PHP根本不检测连接中止 [英] PHP doesn't detect connection abort at all

查看:252
本文介绍了PHP根本不检测连接中止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have read and deeply understood these: 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,事情不工作,如那里所述。我观察到的是:

However, I have tested both PHP 5.1.6 and 5.3 and things DON'T work as described there. What I observe is:


  • connection_status()总是返回true,即使客户端已经关闭连接。

  • 在客户端关闭连接后,即使ignore_user_abort为0,脚本仍会继续执行

  • 在脚本到达结束之前,不会运行register_shutdown_function 。

因此,基本上PHP只是不会中断连接。

So basically PHP just doesn't detect the client's disconnection AT ALL.

请注意,这不像是ignore_user_abort设置为1:如果是这样的话,connection_status()将返回1,即使脚本将保持运行,并且关闭功能将不会被调用直到结束。不是这样。

Note that this is NOT as if ignore_user_abort was set to 1: if that was the case then connection_status() would return 1 even though the script would keep running and the shutdown function would not be called until the end. That is not the case.

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

ini_get("ignore_user_abort") returns 0, as expected.

PHP中的一个错误,或者这可能是由于一些Apache设置?

Is this a bug in PHP, or may this be due to some Apache setting?

如何使PHP如上述文档中所述工作?

How do I get PHP to work as described in the abovementioned documentation?

测试脚本:

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

Steps to reproduce: - visit the url of the script - abort the connection on the client before 10 seconds have elapsed (e.g. hit the stop button in the browser)

预期/期望的行为:
日志应该显示小于10秒的客户端上的连接(例如在浏览器中点击停止按钮) 10点,在结束时myShutdown 1 0(如果你实时观看日志,客户端断开连接时,myShutDown应该立即出现)

Expected/Desired behavior: The logs should show less than 10 dots, and at the end "myShutdown 1 0" (if you watch the log in real time, the myShutDown should appear immediately when the client disconnects)

观察/行为:
日志总是显示正好10个点,在myShutdown 0 0结束时(如果你实时观看,无论客户端断开连接,它都会持续10秒)。

Observed/current behavior: The logs show always exactly 10 dots, and at the end "myShutdown 0 0" (if you watch it in realtime, it goes on for 10 seconds no matter when the client disconnects).

推荐答案

首先,我也没能得到它的工作,使用基本的Ubuntu 12.04 LAMP安装(php5.3)。但我有一些信息,并希望它是有帮助的。任何评论或编辑赞赏! :)

First, I also failed to get it to work, using the basic ubuntu 12.04 LAMP installation (php5.3). But I've some information and hope that it is helpful. Any comments or edits appreciated! :)

我看到你的代码有两个问题。第一个是语法错误。当调用 register_shutdown_function()时,缺少 myShutdown 将行更改为:

I see two problems with your code. The first is a syntax error. You are missing the single quotes around myShutdown when calling register_shutdown_function(). Change the line to:

register_shutdown_function('myShutdown');

我看到的第二个问题是缺少 echo 之后调用 c / c> net / manual / en / function.flush.phprel =nofollow c $ c> s。文档说:

The second problem I see is the missing flush() call after echos. The documentation says:


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

PHP will not detect that the user has aborted the connection until an attempt is made to send information to the client. Simply using an echo statement does not guarantee that information is sent, see flush().

但即使 flush()在任何情况下都不会有帮助。从 flush()的文档:

But even flush() will not help in any case. From the documentation of flush():


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

flush() may not be able to override the buffering scheme of your web server and it has no effect on any client-side buffering in the browser. It also doesn't affect PHP's userspace output buffering mechanism. This means you will have to call both ob_flush() and flush() to flush the ob output buffers if you are using those.

几个服务器,

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

Server modules for Apache like mod_gzip may do buffering of their own that will cause flush() to not result in data being sent immediately to the client.

即使浏览器可能会在显示之前缓冲其输入。例如,Netscape缓冲文本,直到它收到行尾或标签的开头,并且它不会渲染表,直到最外面的表的标签被看到。

Even the browser may buffer its input before displaying it. Netscape, for example, buffers text until it receives an end-of-line or the beginning of a tag, and it won't render tables until the tag of the outermost table is seen.

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

Some versions of Microsoft Internet Explorer will only start to display the page after they have received 256 bytes of output, so you may need to send extra whitespace before flushing to get those browsers to display the page.

在该页面的注释中有一个建议设置几个头和apache配置:

In the comments of the that page there is an advice to set several headers and apache configs:

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

然而,即使这对我没有用。我使用wiresharek调查了这个,虽然网络服务器在0.0037秒后发送内容('Hi'),网络浏览器正在缓冲页面。

however, even this didn't work for me. I've investigated this using wiresharek, although the web server sends content ('Hi') after 0.0037 seconds, the web browser was buffering the page.

这篇关于PHP根本不检测连接中止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆