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 addslashes及其他清除空格的方法是不安全的
Jan 25 PHP
深入for,while,foreach遍历时间比较的详解
Jun 08 PHP
php根据日期判断星座的函数分享
Feb 13 PHP
ThinkPHP3.1基础知识快速入门
Jun 19 PHP
PHP的fsockopen、pfsockopen函数被主机商禁用的解决办法
Jul 08 PHP
php实现图片等比例缩放代码
Jul 23 PHP
PHP 文件上传后端处理实用技巧方法
Jan 06 PHP
php实现图片按比例截取的方法
Feb 06 PHP
PHP使用Redis替代文件存储Session的方法
Feb 15 PHP
PHP框架Laravel中使用UUID实现数据分表操作示例
May 30 PHP
php设计模式之原型模式分析【星际争霸游戏案例】
Mar 23 PHP
PHP优化之批量操作MySQL实例分析
Apr 23 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
用Socket发送电子邮件(利用需要验证的SMTP服务器)
2006/10/09 PHP
PHP+MYSQL开发工具及资源收藏
2007/01/02 PHP
php自动获取关键字的方法
2015/01/06 PHP
php创建、获取cookie及基础要点分析
2015/01/26 PHP
php 如何设置一个严格控制过期时间的session
2017/05/05 PHP
动态表单验证的操作方法和TP框架里面的ajax表单验证
2017/07/19 PHP
网页javascript精华代码集
2007/01/24 Javascript
JS+XML 省份和城市之间的联动实现代码
2009/10/14 Javascript
JavaScript DOM学习第四章 getElementByTagNames
2010/02/19 Javascript
基于jquery的回到页面顶部按钮
2011/06/27 Javascript
JQuery动画和停止动画实例代码
2013/03/01 Javascript
jquery选择器原理介绍($()使用方法)
2014/03/25 Javascript
javascript实现博客园页面右下角返回顶部按钮
2015/02/22 Javascript
jQuery基本选择器之标签名选择器
2016/09/03 Javascript
详解利用exif.js解决ios手机上传竖拍照片旋转90度问题
2016/11/04 Javascript
JS实现的驼峰式和连字符式转换功能分析
2016/12/21 Javascript
微信小程序 页面跳转如何实现传值
2017/04/05 Javascript
基于webpack.config.js 参数详解
2018/03/20 Javascript
浅谈Vue下使用百度地图的简易方法
2018/03/23 Javascript
从零到一详聊创建Vue工程及遇到的常见问题
2019/04/25 Javascript
jsonp实现百度下拉框功能的方法分析
2019/05/10 Javascript
Python异常处理操作实例详解
2018/05/10 Python
Python cv2 图像自适应灰度直方图均衡化处理方法
2018/12/07 Python
python中aioysql(异步操作MySQL)的方法
2019/04/11 Python
Python中bisect的使用方法
2019/12/31 Python
python3注册全局热键的实现
2020/03/22 Python
pycharm中使用request和Pytest进行接口测试的方法
2020/07/31 Python
Django搭建项目实战与避坑细节详解
2020/12/06 Python
HTML5调用手机摄像头拍照的实现思路及代码
2014/06/15 HTML / CSS
HTML5实现音频和视频嵌入的方法
2018/08/22 HTML / CSS
JD Sports德国官网:英国领先的运动鞋和运动服饰零售商
2018/02/26 全球购物
毕业自荐信
2013/12/16 职场文书
2014年中班元旦活动方案
2014/02/14 职场文书
优秀少先队辅导员事迹材料
2014/12/24 职场文书
职场干货:简历中的自我评价应该这样写!
2019/05/06 职场文书
MySQL为id选择合适的数据类型
2021/06/07 MySQL