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 相关文章推荐
桌面中心(二)数据库写入
Oct 09 PHP
php错误、异常处理机制(补充)
May 07 PHP
PHP.ini中配置屏蔽错误信息显示和保存错误日志的例子
May 12 PHP
ThinkPHP3.1的Widget新用法
Jun 19 PHP
PHP获取表单所有复选框的值的方法
Aug 28 PHP
PHP实现支持SSL连接的SMTP邮件发送类
Mar 05 PHP
[原创]ThinkPHP让../Public在模板不解析(直接输出)的方法
Oct 09 PHP
分享PHP计算两个日期相差天数的代码
Dec 23 PHP
Yii2 RESTful中api的使用及开发实例详解
Jul 06 PHP
PHP hex2bin()函数用法讲解
Feb 25 PHP
浅谈PHP无限极分类原理
Mar 14 PHP
Laravel框架实现多个视图共享相同数据的方法详解
Jul 09 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表单提交问题的解决方法
2011/04/12 PHP
php中怎么搜索相关联数组键值及获取之
2013/10/17 PHP
通过MSXML2自动获取QQ个人头像及在线情况(给初学者)
2007/01/22 Javascript
Jquery Ajax学习实例7 Ajax所有过程事件分析示例
2010/03/23 Javascript
模拟电子签章盖章效果的jQuery插件源码
2013/06/24 Javascript
Jquery显示、隐藏元素以及添加删除样式
2013/08/09 Javascript
js和jquery中循环的退出和继续学习记录
2014/09/06 Javascript
如何使用HTML5地理位置定位功能
2015/04/27 Javascript
jquery表单验证插件formValidator使用方法
2016/04/01 Javascript
javascript函数的四种调用模式
2017/01/08 Javascript
将Sublime Text 3 添加到右键中的简单方法
2017/12/12 Javascript
详解vue+axios给开发环境和生产环境配置不同的接口地址
2019/08/16 Javascript
python实现迭代法求方程组的根过程解析
2019/11/25 Javascript
JavaScript设计模式之观察者模式与发布订阅模式详解
2020/05/07 Javascript
python将文本转换成图片输出的方法
2015/04/28 Python
1分钟快速生成用于网页内容提取的xslt
2018/02/23 Python
python-Web-flask-视图内容和模板知识点西宁街
2019/08/23 Python
Python计算指定日期是今年的第几天(三种方法)
2020/03/26 Python
解决django FileFIELD的编码问题
2020/03/30 Python
升级keras解决load_weights()中的未定义skip_mismatch关键字问题
2020/06/12 Python
python归并排序算法过程实例讲解
2020/11/04 Python
纯css3无js实现的Android Logo(有简单动画)
2013/01/21 HTML / CSS
使用CSS3 制作一个material-design 风格登录界面实例
2016/12/12 HTML / CSS
印尼穆斯林时尚购物网站:Hijabenka
2016/12/10 全球购物
英国最大的老式糖果店:A Quarter Of
2017/04/08 全球购物
深深扎根运动世界的生活品牌:Tillys
2017/10/30 全球购物
麦当劳印度网上订餐:McDelivery
2020/03/16 全球购物
自我鉴定书范文
2013/10/02 职场文书
俞敏洪北大演讲稿
2014/05/22 职场文书
片区教研活动总结
2014/07/02 职场文书
化学教育专业自荐信
2014/07/04 职场文书
工作年限证明模板
2014/11/01 职场文书
2014年卫生保健工作总结
2014/12/08 职场文书
简历中自我评价范文
2015/03/11 职场文书
公务员的复习计划书,请收下!
2019/07/15 职场文书
漫改真人电影「萌系男友是燃燃的橘色」公开先导视觉图
2022/03/21 日漫