如何在PHP中禁用输出缓冲 [英] How to disable output buffering in PHP

查看:164
本文介绍了如何在PHP中禁用输出缓冲的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个简单的中继脚本,它连接到网络摄像头并从套接字读取,并使用print函数输出这些数据。数据是已设置边界的MJPG数据。我只输出读取的数据。

I wrote a simple relay script that connects to a web camera and reads from the socket, and outputs this data using the print function. The data is MJPG data with boundaries already setup. I just output the data that is read.

问题是PHP似乎在缓冲这些数据。当我将相机设置为1 FPS时,进纸将冻结7-8秒,然后快速显示8帧。如果我将分辨率设置为一个巨大的尺寸,相机会以大约每秒1帧的速度移动。我假设然后发生了一些缓冲(因为巨大的大小快速填充缓冲区,而低大小则没有),我无法弄清楚如何禁用此缓冲。有谁知道怎么做?

The problem is PHP seems to be buffering this data. When I set the camera to 1 FPS, the feed will freeze for 7-8 seconds, then quickly display 8 frames. If I set the resolution to a huge size, the camera move at more or less 1 frame per second. I assume then some buffering is happening (since huge sizes fill the buffer quickly, and low sizes don't), and I can't figure out how to disable this buffering. Does anyone know how to?

代码:

ignore_user_abort(false);

$boundary = "myboundary";

//Set this so PHP doesn't timeout during a long stream
set_time_limit(0);

$socketConn = @fsockopen ("192.168.1.6", 1989, $errno, $errstr, 2);
if (!$socketConn)
exit();
stream_set_timeout($socketConn, 10);
fputs ($socketConn, "GET /mjpeg HTTP/1.0\r\n\r\n");

//Setup Header Information
header("Cache-Control: no-cache");
header("Cache-Control: private");
header("Pragma: no-cache");
header("Content-type: multipart/x-mixed-replace; boundary=$boundary");

@ini_set('implicit_flush', 1);
for ($i = 0; $i < ob_get_level(); $i++)
ob_end_flush();
ob_implicit_flush(1);

stream_set_blocking($f2, false);

//Send data to client
while (connection_status() == CONNECTION_NORMAL)
{
    $chunk = fread($socketConn, 128);
    print $chunk;   
}

fclose($socketConn);


推荐答案

tl; dr version



做两件事:

tl;dr version

Do two things:


  1. 禁用用户空间输出缓冲区......

  1. Disable the userspace output buffer, either...


  • 在全球范围内,通过...

  • Globally, by either...


  • 在php.ini中关闭 output_buffering ,或

  • 关闭 output_buffering 在您的Apache配置中使用

  • Turning off output_buffering in your php.ini, or
  • Turning off output_buffering in your Apache config using

php_flag "output_buffering" Off


或者只关注您关注的脚本......

or for just the script you care about, by either...


  • 调用 ob_end_flush(),或

  • 调用 ob_end_clean()

  • calling ob_end_flush(), or
  • calling ob_end_clean()

此外,尽可能多地禁用服务器级输出缓冲区:

Also, disable the server-level output buffer as much as you possibly can, by either:


  • 调用 ob_implicit_flush()在您的脚本开头,或

  • 在前夕后调用 flush() ry echo 将输出添加到响应正文的语句或其他语句

  • calling ob_implicit_flush() at the start of your script, or
  • calling flush() after every echo statement or other statement that adds output to the response body



更长的版本



令人困惑的是,有两层缓冲可能是相关的,PHP文档在区分方面表现不佳两者之间。

Longer version

Confusingly, there are two layers of buffering that may be relevant and the PHP documentation does a poor job of distinguishing between the two.

第一层通常被PHP文档称为'输出缓冲区'。此缓冲层仅影响HTTP响应的 body 的输出,而不影响标头。您可以使用 ob_start()打开输出缓冲 ,并使用 ob_end_flush() ob_end_clean() 。您还可以使用 output_buffering 选项。

The first layer is usually referred to by the PHP docs as the 'output buffer'. This layer of buffering only affects output to the body of the HTTP response, not the headers. You can turn on output buffering with ob_start(), and turn it off with ob_end_flush() or ob_end_clean(). You can also have all your scripts automatically start with output buffering on using the output_buffering option in php.ini.

此选项的默认值href =https://github.com/php/php-src/blob/master/php.ini-production =noreferrer> php.ini的生产版本是4096,这意味着首先将4096字节的输出缓冲在输出缓冲区中,此时它将被刷新并且输出缓冲被关闭。

The default value of this option for production versions of php.ini is 4096, which means that the first 4096 bytes of output will be buffered in the output buffer, at which point it will be flushed and output buffering is turned off.

您可以全局禁用此层缓冲通过在php.ini文件中将 output_buffering 设置为 Off (或使用

You can disable this layer of buffering globally by setting output_buffering to Off in your php.ini file (or using

php_flag "output_buffering" Off

在你的Apache配置,如果您使用的是Apache)。或者,您可以通过在开头时调用 ob_end_clean() ob_end_flush()来禁用单个脚本。脚本。

in your Apache config, if you're using Apache). Alternatively, you can disable it for a single script by calling ob_end_clean() or ob_end_flush() at the start of the script.

超出输出缓冲区是PHP手册所指的作为'写缓冲区',以及您的Web服务器具有的任何缓冲系统。如果你通过 mod_php 使用PHP,并且没有使用 mod_gzip ,你可以调用 flush() 来冲洗这些;与其他后端一样,它也可能有用,虽然手册很谨慎地提供保证:

Beyond the output buffer is what the PHP manual refers to as the 'write buffer', plus any buffering system your web server has. If you're using PHP with Apache through mod_php, and are not using mod_gzip, you can call flush() to flush these; with other backends, it might work too, although the manual is cagey about giving assurances:


描述



Description

void flush ( void )

Flushes PHP的写缓冲区和PHP正在使用的后端(CGI,Web服务器等)。这会尝试将当前输出一直推送到浏览器,但需要注意几点。

Flushes the write buffers of PHP and whatever backend PHP is using (CGI, a web server, etc). This attempts to push current output all the way to the browser with a few caveats.

flush()可能无法覆盖缓冲您的Web服务器的方案,它对浏览器中的任何客户端缓冲没有影响。它也不会影响PHP的用户空间输出缓冲机制。这意味着您必须同时调用 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.

还有一对夫妇你可以让PHP自动调用 flush()每次 echo 任何事情(或做任何其他回音输出的事情)回复机构)。

There are also a couple of ways you can make PHP automatically call flush() every time you echo anything (or do anything else that echoes output to the response body).

第一种是打电话给 ob_implicit_flush() 。请注意,此函数具有欺骗性的名称;给定 ob _ 前缀,任何合理的人都会认为它会影响'输出缓冲区',就像 ob_start 一样, ob_flush 等但是,事实并非如此; ob_implicit_flush(),如 flush(),会影响服务器级输出缓冲区,并且不会以任何方式与之交互输出缓冲区由其他 ob _ 函数控制。

The first is to call ob_implicit_flush(). Note that this function is deceptively named; given its ob_ prefix, any reasonable person would expect that it would affect the 'output buffer', as do ob_start, ob_flush etc. However, this is not the case; ob_implicit_flush(), like flush(), affects the server-level output buffer and does not interact in any way with the output buffer controlled by the other ob_ functions.

第二种是通过设置<全局启用隐式刷新a href =http://www.php.net/manual/en/outcontrol.configuration.php#ini.implicit-flush =noreferrer> implicit_flush 在php.ini中标记 On 。这相当于在每个脚本的开头调用 ob_implicit_flush()。请注意,手册建议不要这样做,隐晦地引用严重的性能影响,其中一些我在此探讨切线相关答案

The second is to globally enable implicit flushing by setting the implicit_flush flag to On in your php.ini. This is equivalent to calling ob_implicit_flush() at the start of every script. Note that the manual advises against this, cryptically citing "serious performance implications", some of which I explore in this tangentially related answer.

这篇关于如何在PHP中禁用输出缓冲的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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