PHP flush()与ob_flush()的区别详解


Posted in PHP onJune 03, 2013

buffer ---- flush()
 
buffer是一个内存地址空间,Linux系统默认大小一般为4096(1kb),即一个内存页。主要用于存储速度不同步的设备或者优先级不同的 设备之间传办理数据的区域。通过buffer,可以使进程这间的相互等待变少。这里说一个通俗一点的例子,你打开文本编辑器编辑一个文件的时候,你每输入 一个字符,操作系统并不会立即把这个字符直接写入到磁盘,而是先写入到buffer,当写满了一个buffer的时候,才会把buffer中的数据写入磁 盘,当然当调用内核函数flush()的时候,强制要求把buffer中的脏数据写回磁盘。
同样的道理,当执行echo,print的时候,输出并没有立即通过tcp传给客户端浏览器显示, 而是将数据写入php buffer。php output_buffering机制,意味在tcp buffer之前,建立了一新的队列,数据必须经过该队列。当一个php buffer写满的时候,脚本进程会将php buffer中的输出数据交给系统内核交由tcp传给浏览器显示。所以,数据会依次写到这几个地方echo/pring -> php buffer -> tcp buffer -> browser

php output_buffering --- ob_flush()

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

这两个函数的使用怕是很多人最迷惑的一个问题,手册上对两个函数的解释也语焉不详,没有明确的指出它们的区别,似乎二者的功能都是刷新输出缓存。但在我们文章一开始的代码中如果讲fush()替换成ob_flush(),程序就再不能正确执行了。显然,它们是有区别的,否则也手册中直接说明其中一个是另外一个函数的别名即可了,没必要分别说明。那么它们的区别到底是什么呢?

在没有开启缓存时,脚本输出的内容都在服务器端处于等待输出的状态 ,flush()可以将等待输出的内容立即发送到客户端。

开启缓存后,脚本输出的内容存入了输出缓存中 ,这时没有处于等待输出状态的内容,你直接使用flush()不会向客户端发出任何内容。而 ob_flush()的作用就是将本来存在输出缓存中的内容取出来,设置为等待输出状态,但不会直接发送到客户端 ,这时你就需要先使用 ob_flush()再使用flush(),客户端才能立即获得脚本的输出。

一. flush和ob_flush的正确顺序,正确应是,先ob_flush再flush,如下:
ob_flush();
flush();
如果Web服务器的操作系统是windows系统,那顺序颠倒或者不使用ob_flush()也不会出现问题。[有待求证 ] 但是在Linux系统上就无法刷新输出缓冲。

output buffering函数
1.bool ob_start ([ callback $output_callback [, int $chunk_size [, bool $erase ]]] )
激活output_buffering机制。一旦激活,脚本输出不再直接出给浏览器,而是先暂时写入php buffer内存区域。
php默认开启output_buffering机制,只不过,通过调用ob_start()函数据output_buffering值扩展到足够 大 。也可以指定$chunk_size来指定output_buffering的值。$chunk_size默认值是0,表示直到脚本运行结束,php buffer中的数据才会发送到浏览器。如果你设置了$chunk_size的大小 ,则表示只要buffer中数据长度达到了该值,就会将buffer中 的数据发送给浏览器。
当然,你可以通过指定$ouput_callback,来处理buffer中的数据。比如函数ob_gzhandler,将buffer中的数据压缩后再传送给浏览器。
第三个参数:是否擦除缓存,可选,默认是true,如果设置为false,则在脚本执行结束前,缓存都不会被清除。
2.ob_get_contents
获取一份php buffer中的数据拷贝。值得注意的是,你应该在ob_end_clean()函数调用前调用该函数,否则ob_get_contents()返回一个空字符中。

可以使用ob_get_contents()以字符串形式获取服务端缓存的数据,
使用ob_end_flush()则会输出被缓存起来的数据,并关闭缓存。
而使用ob_end_clean()则会静默的清除服务端缓存的数据,而不会有任何数据或其他行为。
服务端的缓存是堆叠起来的,也就是说你在开启了ob_start()后,关闭之前,在其内部还 可以开启另外一个缓存ob_start()。

不过你也要务必保证关闭缓存的操作和开启缓存的操作数量一样多。
ob_start() 可以指定一个回调函数来处理缓存数据,如果一个ob_start()内部嵌套了另一个ob_start(),我们假定,外层的ob_start(),编号是A,内层的ob_start()编号是B,它们各自制定了一个回调函数分别是functionA和functionB,那么在缓存B中的数据输出时,它会先辈funcitonB回调函数处理,再交给外层的functionA回调函数处理,之后才能输出到客户端。

另外,手册说,对于某些web服务器,比如apache,在使用回调函数有可能会改变程序当前的工作目录,解决方法是在回调函数中自行手动把工作目录修改回来,用chdir函数,这点似乎不常遇到,遇到的时候记得去查手册吧。

3.ob_end_flush与ob_end_clean
这二个函数有点相似,都会关闭ouptu_buffering机制。但不同的是,ob_end_flush只是把php buffer中的数据冲(flush/send)到客户端浏览器,而ob_clean_clean将php bufeer中的数据清空(erase),但不发送给客户端浏览器。

ob_end_flush调用之前 ,php buffer中的数据依然存在,ob_get_contents()依然可以获取php buffer中的数据拷贝。

而ob_end_flush()调用之后 ob_get_contents()取到的是空字符串,同时浏览器也接收不到输出,即没有任何输出。

可以使用ob_get_contents()以字符串形式获取服务端缓存的数据,使用ob_end_flush()则会输出被缓存起来的数据,并关闭缓存。
而使用ob_end_clean()则会静默的清除服务端缓存的数据,而不会有任何数据或其他行为。
服务端的缓存是堆叠起来的,也就是说你在开启了ob_start()后,关闭之前,在其内部还可以开启另外一个缓存ob_start()。不过你也要务必保证关闭缓存的操作和开启缓存的操作数量一样多。
ob_start() 可以指定一个回调函数来处理缓存数据,如果一个ob_start()内部嵌套了另一个ob_start(),我们假定,外层的ob_start(),编号是A,内层的ob_start()编号是B,它们各自制定了一个回调函数分别是functionA和functionB,那么在缓存B中的数据输出时,它会先辈funcitonB回调函数处理,再交给外层的functionA回调函数处理,之后才能输出到客户端。

另外,手册说,对于某些web服务器,比如apache,在使用回调函数有可能会改变程序当前的工作目录,解决方法是在回调函数中自行手动把工作目录修改回来,用chdir函数,这点似乎不常遇到,遇到的时候记得去查手册吧。

PHP 相关文章推荐
PHP 采集程序中常用的函数
Dec 09 PHP
php木马webshell扫描器代码
Jan 25 PHP
PHP基础之运算符的使用方法
Apr 28 PHP
关于JSON以及JSON在PHP中的应用技巧
Nov 27 PHP
phpmailer在服务器上不能正常发送邮件的解决办法
Jul 08 PHP
教你如何开启shopnc b2b2c 伪静态
Oct 21 PHP
Yii2中使用asset压缩js,css文件的方法
Nov 24 PHP
PHP+Ajax 检测网络是否正常实例详解
Dec 16 PHP
PHP脚本自动识别验证码查询汽车违章
Dec 20 PHP
PHP里面把16进制的图片数据显示在html的img标签上(实现方法)
May 02 PHP
PHP数组对象与Json转换操作实例分析
Oct 22 PHP
php设计模式之组合模式实例详解【星际争霸游戏案例】
Mar 27 PHP
PHP导出EXCEL快速开发指南--PHPEXCEL的使用详解
Jun 03 #PHP
PHP Cookie的使用教程详解
Jun 03 #PHP
PHP register_shutdown_function函数的深入解析
Jun 03 #PHP
深入PHP与浏览器缓存的分析
Jun 03 #PHP
PHP判断图片格式的七种方法小结
Jun 03 #PHP
基于session_unset与session_destroy的区别详解
Jun 03 #PHP
PHP批量采集下载美女图片的实现代码
Jun 03 #PHP
You might like
在PHP中设置、使用、删除Cookie的解决方法
2013/05/06 PHP
thinkphp实现多语言功能(语言包)
2014/03/04 PHP
YII框架模块化处理操作示例
2019/04/26 PHP
PHP超低内存遍历目录文件和读取超大文件的方法
2019/05/01 PHP
Nigma vs Alliance BO5 第一场2.14
2021/03/10 DOTA
jquery 1.4.2发布!主要是性能与API
2010/02/25 Javascript
3Z版基于jquery的图片复选框(asp.net+jquery)
2010/04/12 Javascript
JS按位非(~)运算符与~~运算符的理解分析
2011/07/31 Javascript
javascript实现可改变滚动方向的无缝滚动实例
2013/06/17 Javascript
jquery对dom的操作常用方法整理
2013/06/25 Javascript
js转义字符介绍
2013/11/05 Javascript
JS将数字转换成三位逗号分隔的样式(示例代码)
2014/02/19 Javascript
Javascript技术难点之apply,call与this之间的衔接
2015/12/04 Javascript
JavaScript基础篇(6)之函数表达式闭包
2015/12/11 Javascript
jQuery获取radio选中项的值实例
2016/06/18 Javascript
新手vue构建单页面应用实例代码
2017/09/18 Javascript
Vue结合Video.js播放m3u8视频流的方法示例
2018/05/04 Javascript
JS中Promise函数then的奥秘探究
2018/07/30 Javascript
Vuejs+vue-router打包+Nginx配置的实例
2018/09/20 Javascript
使用node.JS中的url模块解析URL信息
2020/02/06 Javascript
基于vue+element实现全局loading过程详解
2020/07/10 Javascript
JQuery使用数组遍历跳出each循环
2020/09/01 jQuery
详解vue修改elementUI的分页组件视图没更新问题
2020/11/13 Javascript
[01:27:30]LGD vs Newbee 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/19 DOTA
Pytorch自己加载单通道图片用作数据集训练的实例
2020/01/18 Python
HTML5 history新特性pushState、replaceState及两者的区别
2015/12/26 HTML / CSS
苏格兰在线威士忌商店:The Whisky Barrel
2019/05/07 全球购物
周生生珠宝香港官网:Chow Sang Sang(香港及海外配送)
2019/09/05 全球购物
建房协议书
2014/04/11 职场文书
公司委托书怎么写
2014/08/02 职场文书
工作作风建设心得体会
2014/10/22 职场文书
2014年涉外离婚协议书范本
2014/11/20 职场文书
2015年信访维稳工作总结
2015/04/07 职场文书
债务纠纷代理词
2015/05/25 职场文书
主持人开场白台词
2015/05/29 职场文书
在Windows下安装配置CPU版的PyTorch的方法
2021/04/02 Python