PHP 缓冲区 ob_flush() 与 flush()

Posted

技术标签:

【中文标题】PHP 缓冲区 ob_flush() 与 flush()【英文标题】:PHP buffer ob_flush() vs. flush() 【发布时间】:2011-05-10 15:14:31 【问题描述】:

ob_flush()flush() 之间有什么区别,为什么我必须同时调用这两个?

ob_flush() reference 说:

此函数将发送输出缓冲区的内容(如果有)。

flush() reference 说:

刷新 php 的写入缓冲区以及 PHP 正在使用的任何后端(CGI、Web 服务器等)。

但是,它继续说:

[it] 可能无法覆盖您的 Web 服务器的缓冲方案...

所以,在我看来,我可以一直使用ob_flush()。但是,当我这样做时,我会得到奇怪的结果。有人可以简单地解释一下这里发生了什么吗?

【问题讨论】:

【参考方案1】:

ob_flush 发送一个应用程序启动的缓冲区。在任何 PHP 脚本中可能有多个嵌套的ob_start()ob_flush 将当前内容传递给上层。

PHP 本身可能(自行决定)缓冲输出。这取决于后端。但通常FastCGI 有自己的套接字缓冲区。因此还需要调用flush() 将当前内容发送到Web 服务器。

现在,Web 服务器本身可能会实现另一个缓冲方案(mod_deflate 或内容过滤器),您对此没有任何影响。但这很少见,因为需要专门配置。

不管怎样,两者都用。

【讨论】:

使用 ob_flush 和 flush 并按顺序使用它们。 这个答案中缺少的重要细节是output_buffering 配置选项,其在生产版本的 php.ini 中的默认值为 4096。这意味着当任何 PHP 脚本启动时,前 4096 个字节输出被缓冲(在可使用ob_flush() 刷新的缓冲区中)。这就是为什么必须使用ob_flush()flush() 的原因。通过 php.ini 禁用 output_buffering 或在脚本开头调用 ob_end_clean()ob_end_flush() 消除了这种必要性。 感谢@MarkAmery,但“脚本开头”处的ob_end_clean() 似乎违反直觉。你的意思是我们应该在ob_start() 之后和两次刷新之前包括这个? 好吧,我在脚本的开头有一个ob_start() 和一个ob_end_clean()。然后在脚本期间的任何“回声”之后,我还包括ob_flush(); flush();,我希望在脚本花费时间的同时,到目前为止所做的任何事情都会输出到屏幕上(在浏览器中)。但是直到最后什么都没有。我错过了什么? @KhomNazid 浏览器观察与调试 HTTP 流不同。对不完整 html DOM 的增量和延迟输出不太可能是可见的。使用您当前的设置进行一些 CLI 测试。 (然后,并且只有在那时,开始一个不同的问题。)【参考方案2】:

ob_flush 刷新使用ob_start 等函数创建的输出缓冲区

flush 将 PHP 脚本本身的缓冲输出刷新给调用者

【讨论】:

【参考方案3】:

ob_flush() 是高级刷新。它刷新高级缓冲区并将所有内容放入准备发送的低级内部缓冲区。

请注意,ob_ 系列函数会创建 堆栈 缓冲区,因此如果编写代码是为了利用这一优势,只是盲目地到处写 ob_flush() 确实会给您带来“奇怪的结果”这种堆叠。

flush() 是低级刷新,指示 PHP 刷新其内部的低级数据缓冲区。

在此之下,还有套接字层缓冲区;在此之下,有网络层缓冲区。并且,在最低层,沿着数据电缆向下的电子队列。

【讨论】:

好吧,我在脚本的开头有一个ob_start() 和一个ob_end_clean()。然后在脚本期间的任何“回声”之后,我还包括ob_flush(); flush();,并且我希望在脚本花费时间的同时,到目前为止所做的任何事情都会输出到屏幕上(在浏览器中)。但是直到最后什么都没有。我错过了什么? @KhomNazid 按中间阶段缓冲,例如网络服务器、代理、浏览器...【参考方案4】:

我猜这与您的previous question 有关。使用输出缓冲的显着优势在于它与数据压缩一起使用。如果您不使用ob_gzhandler,则几乎没有什么收获。 flush 将仅提交仍在服务器上的任何输出数据。使用ob_start 及其对应的ob_flushob_end_cleanob_end_flush,任何等待压缩的内容(查看flushob_flush 指代不同的存储桶-ob 将数据发送到flush , flush 将数据发送到浏览器 - 可能不准确,但这就是想法)将被打包并发送到客户端。

【讨论】:

谢谢,桶类比是一个很好的例子。

以上是关于PHP 缓冲区 ob_flush() 与 flush()的主要内容,如果未能解决你的问题,请参考以下文章

php ob_flush 和flush

PHP IIS 环境 ob_flush()刷新缓冲区执行完才显示 解决办法,iis缓冲区原因

ob_flush()和flush()和ob_implicit_flush(true)

PHP flush()与ob_flush()的区别

php定时执行操作及ob_flush()与flush()的使用

php函数ob_start()ob_end_clean()ob_get_contents()