首页 新闻 会员 周边

关于ob_end_flush()无效问题?

0
悬赏园豆:50 [已解决问题] 解决于 2011-12-07 10:31

最近初学php web编程,写了一个简单demo,理论上调用ob_end_flush()后,前端应该显示网页内容,但是却出现了下面的情况,

<?php
ob_start();

include 'test.tpl.php';

ob_end_flush();

//---------------------------------------------------------------------
// invoke client js

$s1 = sprintf("\n<script>%s.%s();</script>", 'oCar', 'updateDiv1');

// output the buffer to client
echo $s1;
unset($s1);
@flush();

//----------------------------------------------------------------------
sleep(2);
// invoke client js
$s2 = sprintf("\n<script>%s.%s();</script>", 'oCar', 'updateDiv2');

// output the buffer to client
echo $s2;
unset($s2);
@flush();

php.ini中,如果设定output_buffering = On,刚需要执行完整个php代码才能显示出来;

如果设定output_buffering = Off,则需要执行到第一个@flush()时才会显示出网页来,

为什么不是调用ob_end_flush()后,就显示出网页呢?

kevens的主页 kevens | 初学一级 | 园豆:6
提问于:2011-12-02 09:57
< >
分享
最佳答案
0

你可能没有搞清楚PHP buffer的机制。

PHP的buffer是这样的:输出的字符串 => PHP buffer => 等待输出 => web 服务器的缓冲区 => tcp 缓冲区 => 客户端。过程其实相当的复杂。我大概和你说说几个函数的工作机制吧:

bool ob_start    ([ callback $output_callback   [, int $chunk_size   [, bool $erase  ]]] ) 这个函数我关键要强调一下第二个参数:

如果可选参数 chunk_size 被赋值了,在任何一个能引起缓冲区的长度等于   或超过 chunk_size 的输出操作后,缓冲区都会被刷送。   默认值 0 意味着脚本结束之后,缓冲区会被刷送,其余的特殊值可以将 chunk_size从 1 设定到 4096。  这个参数默认是0.

还有一点,缓冲区是可以嵌套的。这点非常关键。比如你调用了两次ob_start ,就会创建用两个缓冲区。第二次创建的缓冲区,会写入第一次创建的缓冲区,而ob_start 创建的缓冲区,总是会写入output_buffering =ON 时候系统自动创建的缓冲区。

我们再来看一下:ob_end_flush ,这个函数的作用是把最后一次打开的缓冲区关闭掉,并把内容送入下一个缓冲区。如果下一个缓冲区没有,就进入等待输出的状态了。

flush是刷新等待输出的内容去浏览器。前提是内容是等待输出的状态了,而不是在缓冲区中,它不会影响缓冲区的内容。

再来看你的代码:

如果output_buffering = On ,那么系统会默认创建一个缓冲区,这个大小一般是2K. ob_end_flush的内容会进入这个缓冲区,而不会进入输出等待。所以调用flush一点效果都没有。直到脚本结束,PHP送出所有的内容。

如果output_buffering = Off ob_end_flush的内容会进入输出等待状态,这个时候flush一下,内容就能输出了。

当然,这个只是PHP这一端的情况分析。还会有其他的因数影响最终的输出:

     个别web服务器程序,特别是Win32下的web服务器程序,在发送结果到浏览器之前,仍然会缓存脚本的输出,直到程序结束为止。   

     有些Apache的模块,比如mod_gzip,可能自己进行输出缓存,这将导致flush()函数产生的结果不会立即被发送到客户端浏览器。   

     甚至浏览器也会在显示之前,缓存接收到的内容。例如 Netscape 浏览器会在接受到换行或 html 标记的开头之前缓存内容,并且在接受到 </table> 标记之前,不会显示出整个表格。   

     一些版本的 Microsoft Internet Explorer 只有当接受到的256个字节以后才开始显示该页面,所以必须发送一些额外的空格来让这些浏览器显示页面内容。

 

收获园豆:50
暮夏 | 菜鸟二级 |园豆:391 | 2011-12-07 00:40
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册