为了账号安全,请及时绑定邮箱和手机立即绑定

如何在PHP中禁用输出缓冲

如何在PHP中禁用输出缓冲

PHP
拉风的咖菲猫 2019-12-02 13:06:02
我编写了一个简单的中继脚本,该脚本连接到网络摄像机并从套接字读取数据,并使用打印功能输出此数据。数据是已设置边界的MJPG数据。我只是输出读取的数据。问题是PHP似乎正在缓冲这些数据。当我将相机设置为1 FPS时,Feed将冻结7-8秒,然后快速显示8帧。如果将分辨率设置为很大,则相机每秒将以大约1帧的速度移动。我假设那时正在发生一些缓冲(因为大尺寸的缓冲区会很快填充,而小尺寸的缓冲区不会填充),而且我不知道如何禁用此缓冲。有人知道怎么做吗?码:ignore_user_abort(false);$boundary = "myboundary";//Set this so PHP doesn't timeout during a long streamset_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 Informationheader("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 clientwhile (connection_status() == CONNECTION_NORMAL){    $chunk = fread($socketConn, 128);    print $chunk;   }fclose($socketConn);
查看完整描述

3 回答

?
呼如林

TA贡献1798条经验 获得超3个赞

做两件事:


禁用用户空间输出缓冲区,或者...


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


output_buffering在您的php.ini中关闭,或

output_buffering使用以下命令在Apache配置中关闭


php_flag "output_buffering" Off

或仅针对您关心的脚本,通过以下任一方式...


致电ob_end_flush(),或

呼唤 ob_end_clean()

另外,通过以下任一方法,尽可能禁用服务器级别的输出缓冲区:


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

flush()在每个echo将输出添加到响应主体的语句或其他语句之后调用

较长的版本

令人困惑的是,可能存在两个相关的缓冲层,PHP文档在区分这两个方面做得很差。


输出缓冲区

PHP文档通常将第一层称为“输出缓冲区”。此缓冲层仅影响到HTTP响应正文的输出,而不影响标头。您可以使用打开缓冲输出ob_start(),ob_end_flush()或者使用或将其关闭ob_end_clean()。您还可以使用output_bufferingphp.ini中的选项使所有脚本自动从输出缓冲开始。


对于生产版本的php.ini,此选项的默认值为4096,这意味着将在输出缓冲区中缓冲输出的前4096个字节,这时将对其进行刷新并关闭输出缓冲。


您可以通过在php.ini文件中将设置output_buffering为Off(或使用


php_flag "output_buffering" Off

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


写缓冲区和Web服务器缓冲区

PHP手册将输出缓冲区之外的内容称为“写缓冲区”,以及Web服务器具有的任何缓冲系统。如果您通过mod_php和结合使用PHP和Apache ,而没有使用mod_gzip,则可以调用flush()来刷新它们;否则,您可以调用。与其他后端一样,它也可能会起作用,尽管该手册对提供保证不屑一顾:


描述

void flush ( void )

刷新PHP的写缓冲区以及PHP使用的任何后端PHP(CGI,Web服务器等)。这会尝试将当前输出一直推送到浏览器,但有一些警告。


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


还有两种方法可以使PHP flush()每次您进行echo任何操作(或执行将输出回显到响应正文的任何其他操作)时自动调用。


首先是打电话ob_implicit_flush()。请注意,该函数被欺骗性命名。鉴于其ob_前缀,任何理智的人会认为它会影响到“输出缓冲”,因为这样做ob_start,ob_flush但是,这种情况并非如此; ob_implicit_flush()像一样flush(),会影响服务器级别的输出缓冲区,并且不会与其他ob_功能控制的输出缓冲区发生任何交互。


第二种是通过在php.ini 中将implicit_flush标志设置为来全局启用隐式刷新On。这等效于ob_implicit_flush()在每个脚本的开头进行调用。请注意,本手册以“严重的性能隐含性”为例,对此建议不多,我在与切向相关的答案中对此进行了探讨。


查看完整回答
反对 回复 2019-12-02
?
慕哥9229398

TA贡献1877条经验 获得超6个赞

除了禁用输出缓冲外,您还可以flush()在每次读取操作之后进行调用。这避免了麻烦服务器配置,并使脚本更具可移植性。


查看完整回答
反对 回复 2019-12-02
?
森林海

TA贡献2011条经验 获得超2个赞

输出缓冲可以分层,在某些情况下,较早的代码已达到多个级别。这将清除所有内容。


while (ob_get_level()) ob_end_clean(); 

// or ob_end_flush() if you want the contents of the buffer.


查看完整回答
反对 回复 2019-12-02
  • 3 回答
  • 0 关注
  • 1064 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信