gpt4 book ai didi

php - 如何在 PHP 中禁用输出缓冲

转载 作者:IT王子 更新时间:2023-10-29 01:14:51 27 4
gpt4 key购买 nike

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

问题是 PHP 似乎正在缓冲这些数据。当我将相机设置为 1 FPS 时,提要会卡住 7-8 秒,然后快速显示 8 帧。如果我将分辨率设置为很大,相机会以每秒或多或少 1 帧的速度移动。我假设当时正在发生一些缓冲(因为大尺寸会快速填充缓冲区,而小尺寸不会),我不知道如何禁用这种缓冲。有人知道怎么做吗?

代码:

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 版本

做两件事:

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

    • 在全局范围内,由任一...

      • 关闭 php.ini 中的 output_buffering,或
      • 在 Apache 配置中使用

        关闭 output_buffering
        php_flag "output_buffering" Off
    • 或者只是你关心的脚本,通过...

      • 调用 ob_end_flush(),或
      • 调用 ob_end_clean()
  2. 另外,尽可能多地禁用服务器级输出缓冲区,方法是:

    • 在脚本开始时调用 ob_implicit_flush(),或者
    • 在每个 echo 语句或将输出添加到响应正文的其他语句之后调用 flush()

加长版

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

输出缓冲区

第一层通常被 PHP 文档称为“输出缓冲区”。这一缓冲层仅影响到 HTTP 响应的 body 的输出,而不影响 header 。您可以使用 ob_start() 打开输出缓冲。 ,然后使用 ob_end_flush() 将其关闭或 ob_end_clean() .您还可以使用 output_buffering 让所有脚本自动从输出缓冲开始。 php.ini 中的选项。

此选项的默认值为production versions of php.ini为 4096,表示输出的前 4096 字节将被缓冲在输出缓冲区中,此时将被刷新并关闭输出缓冲。

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

php_flag "output_buffering" Off

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

写缓冲区和网络服务器缓冲区

除了输出缓冲区之外,还有 PHP 手册中称为“写入缓冲区”的内容,以及您的 Web 服务器拥有的任何缓冲系统。如果您通过 mod_php 将 PHP 与 Apache 一起使用,并且不使用 mod_gzip,则可以调用 flush()冲洗这些;与其他后端一起使用,它可能也可以工作,尽管手册对提供保证很谨慎:

Description

void flush ( void )

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() 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 在每次 echo 任何内容(或执行任何其他将输出回显到响应正文的操作)时自动调用 flush() )。

首先是调用ob_implicit_flush() .请注意,此函数的名称具有欺骗性;给定它的 ob_ 前缀,任何合理的人都会期望它会影响“输出缓冲区”,就像 ob_startob_flush 等一样。但是,不是这种情况; ob_implicit_flush()flush() 一样,影响服务器级别的输出缓冲区,并且不会与其他 ob_< 控制的输出缓冲区进行任何交互 函数。

第二个是通过设置 implicit_flush 来全局启用隐式刷新。在 php.ini 中标记为 On。这相当于在每个脚本的开头调用 ob_implicit_flush()。请注意,手册建议不要这样做,隐晦地引用了“严重的性能影响”,其中一些我在 tangentially related answer 中进行了探讨。 .

关于php - 如何在 PHP 中禁用输出缓冲,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8882383/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com