在看一些代码时,对缓冲区的刷新存在很多疑问,上网搜了一些相关的文章,逐渐有了一定的理解。

主要参考了以下的文章:

http://www.cnblogs.com/mutuan/archive/2012/03/18/2404957.html

http://m.blog.csdn.net/blog/superhosts/42292053

    1. 缓冲区

    首先要理解使用php编程时,这里有两个缓冲区:一个是PHP本身的缓冲区,另外一个可以理解成TCP的缓冲区。

     默认情况下,php buffer是开启的,而且该buffer默认值是4096,即4kb。可以通过在php.ini配置文件中找到output_buffering配置。当echo,print等输出用户数据的时候,输出数据都会写入到php output_buffering中,直到output_buffering写满,会将这些数据通过tcp传送给浏览器显示,所以,数据会依次写到这几个地方echo/pring -> php buffer -> tcp buffer -> browser。也可以通过 ob_start()手动激活php output_buffering机制,使得即便输出超过了4kb数据,也不把数据交给tcp传给浏览器,因为ob_start()将php buffer空间设置到了足够大 。只有直到脚本结束,或者调用ob_end_flush函数,才会把数据发送给客户端浏览器。

 

    2.在PHP中与刷新缓冲相关的函数有三个:

1). flush
      刷新PHP程序的缓冲,而不论PHP执行在何种情况下。该函数将当前为止程序的所有输出发送到用户的浏览器。 但是该函数不会对服务器或客户端浏览器的缓存模式产生任何影响,也不会对PHP本身的缓存产生任何影响。

2). ob_flush

     该函数对PHP本身的的缓存进行输出。PHP本身的缓存受php.ini中的output_buffering的控制。ob_flush()的作用就是将本来存在输出缓存中的内容取出来,设置为等待输出状态,但不会直接发送到客户端,这时你就需要先使用ob_flush()再使用flush(),客户端才能立即获得脚本的输出。

    与PHP本身输出缓冲相关的两个PHP配置是:
      参数1:output_buffering :on/off 或 者整数 。设置为on时,将在所有脚本中使用输出缓存控制,不限制缓存的大小。而设置为整数时,如output_buffering=4096,当缓存数 据达到4096字节时会自动输出刷新缓存。而这个参数的不同正是导致以上代码在不同时候执行结果不同的原因。当output_buffering关闭时, 脚本所有的输出(echo)都会即时发送到客户端,执行上面代码时就是每秒输出一个数字。而开启output_buffering后,输出内容就会先缓存 在服务端,直到脚本结束时才一起发送给客户端。
     参数2:implicit_flush:on/off。设定ON意味着,当脚本有输出时,自动立即发送到客户端。相当于在echo后自动加flush()。


3).ob_implicit_flush

这个函数强制每当有输出的时候,即刻把输出发送到浏览器。这样就不需要每次输出(echo)后,都用flush()来发送到浏览器了。

以下是举例:

1 <?php  
2 ob_end_clean();  
3 echo str_pad(" ", 256);  
4 for ($i=100; $i>0; $i--) {  
5    echo $i, \'<br/>\';  
6    flush();  
7    sleep(1);   
8 }   
9 ?>  

以上代码应该隔一秒钟输出一次$i.  以上echo str_pad(" ", 256)的目的是IE需要接受到256个字节之后才开始显示。 以上代码还有以下两种写法。

<?php  
echo str_pad(" ", 256);  
for ($i=100; $i>0; $i--) {  
   echo $i, \'<br />\';  
   ob_flush();  
   flush();  
   sleep(1);   
}   
?>  
<?php  
ob_implicit_flush(true);  
echo str_pad(" ", 256);  
for ($i=100; $i>0; $i--) {  
   echo $i, \'<br />\';  
   ob_flush();  
   sleep(1);   
}   
?> 

 

另外我们还需要注意刷新缓冲不光受以上几方面的影响,还受以下影响:

       个别web服务器程序,特别是Win32下的web服务器程序,在发送结果到浏览器之前,仍然会缓存脚本的输出,直到程序结束为止。有些Apache的模块,比如mod_gzip,可能自己进行输出缓存,这将导致flush()函 数产生的结果不会立即被发送到客户端浏览器。甚至浏览器也会在显示之前,缓存接收到的内容。例如 Netscape 浏览器会在接受到换行或 html 标记的开头之前缓存内容,并且在接受到 </table> 标记之前,不会显示出整个表格。一些版本的 Microsoft Internet Explorer 只有当接受到的256个字节以后才开始显示该页面,所以必须发送一些额外的空格来让这些浏览器显示页面内容。

 

输出缓冲区相关函数主要有:

  • ob_start() - 打开输出控制缓冲
  • ob_get_length() - 返回输出缓冲区的长度
  • ob_get_level() - 返回输出缓冲区的嵌套级别
  • ob_get_status() - 返回输出缓冲区的状态(数组形式返回,默认返回最顶层,参数为true时返回所有)
  • ob_get_contents() - 返回输出缓冲区的内容
  • ob_get_clean() - 以字符串格式返回当前输出缓冲区并关闭输出缓冲
  • ob_end_clean() - 清空(擦除)缓冲区并关闭输出缓冲
  • ob_get_flush() - 以字符串返回输出缓冲区内容并关闭缓冲
  • ob_end_flush() - 冲刷出(送出)输出缓冲区内容缓冲