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 相关文章推荐
初探PHP5
Oct 09 PHP
php数组函数序列之sort() 对数组的元素值进行升序排序
Nov 02 PHP
浅析PHP中的字符串编码转换(自动识别原编码)
Jul 02 PHP
php+MySQL判断update语句是否执行成功的方法
Aug 28 PHP
php支付宝手机网页支付类实例
Mar 04 PHP
php用户注册信息验证正则表达式
Nov 12 PHP
学习php设计模式 php实现装饰器模式(decorator)
Dec 07 PHP
WordPress开发中自定义菜单的相关PHP函数使用简介
Jan 05 PHP
详解PHP的Yii框架中组件行为的属性注入和方法注入
Mar 18 PHP
浅谈php中urlencode与rawurlencode的区别
Sep 05 PHP
浅谈PHP发送HTTP请求的几种方式
Jul 25 PHP
PHP 应用容器化以及部署方法
Feb 12 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
WordPress的文章自动添加关键词及关键词的SEO优化
2016/03/01 PHP
PHP中md5()函数的用法讲解
2019/03/30 PHP
Javascript 设计模式(二) 闭包
2010/05/26 Javascript
JQuery在光标位置插入内容的实现代码
2010/06/18 Javascript
如何在JavaScript中实现私有属性的写类方式(一)
2013/12/04 Javascript
ExtJS4给Combobox设置列表中的默认值示例
2014/05/02 Javascript
文字垂直滚动之javascript代码
2015/07/29 Javascript
js实现鼠标点击文本框自动选中内容的方法
2015/08/20 Javascript
javascript实现base64 md5 sha1 密码加密
2015/09/09 Javascript
基于jQuery1.9版本如何判断浏览器版本类型
2016/01/12 Javascript
javascript设计模式之策略模式学习笔记
2017/02/15 Javascript
Node 自动化部署的方法
2017/10/17 Javascript
laravel5.3 vue 实现收藏夹功能实例详解
2018/01/21 Javascript
vue.js使用代理和使用Nginx来解决跨域的问题
2018/02/03 Javascript
javascript验证form表单数据的案例详解
2019/03/25 Javascript
Vue分页器实现原理详解
2019/06/28 Javascript
vue 对axios get pust put delete封装的实例代码
2020/01/05 Javascript
ES11新增的这9个新特性,你都掌握了吗
2020/10/15 Javascript
python实现多线程暴力破解登陆路由器功能代码分享
2015/01/04 Python
python执行等待程序直到第二天零点的方法
2015/04/23 Python
Python 中的with关键字使用详解
2016/09/11 Python
Python爬取三国演义的实现方法
2016/09/12 Python
Python快速从注释生成文档的方法
2016/12/26 Python
浅谈Python生成器generator之next和send的运行流程(详解)
2017/05/08 Python
Python AES加密模块用法分析
2017/05/22 Python
Python3编码问题 Unicode utf-8 bytes互转方法
2018/10/26 Python
wxpython布局的实现方法
2019/11/01 Python
python读取tif图片时保留其16bit的编码格式实例
2020/01/13 Python
一文带你了解Python 四种常见基础爬虫方法介绍
2020/12/04 Python
DHC中国官方购物网站:日本通信销售No.1化妆品
2016/08/20 全球购物
Hotels.com爱尔兰:全球酒店预订
2017/02/24 全球购物
户外活动策划方案
2014/03/12 职场文书
秘书英文求职信
2014/04/16 职场文书
党的群众路线教育实践活动教师自我剖析材料
2014/10/09 职场文书
2014年法院个人工作总结
2014/12/17 职场文书
语文教师求职信范文
2015/03/20 职场文书