PHP ob_flush flush 与http chunk分块

ob_flush 官方文档:

ob_flush 输出缓冲区中的内容,这里说的缓冲区就是php本身的buffer 。

php 查看buffer:

开启后默认的大小为4096个字节
也就是说当我们用php 进行echo ,print_r的时候数据是不会立马输出到浏览器的,而是缓存在php的buffer里面

flush 官方文档:

摘自:https://www.laruence.com/2010/04/15/1414.html

其实, 他们俩的操作对象不同, 有些情况下, flush根本不做什么事情..
ob_*系列函数, 是操作PHP本身的输出缓冲区.
所以, ob_flush是刷新PHP自身的缓冲区.
而flush, 严格来讲, 这个只有在PHP做为apache的Module(handler或者filter)安装的时候, 才有实际作用. 它是刷新WebServer(可以认为特指apache)的缓冲区.
在apache module的sapi下, flush会通过调用sapi_module的flush成员函数指针, 间接的调用apache的api: ap_rflush刷新apache的输出缓冲区, 当然手册中也说了, 有一些apache的其他模块, 可能会改变这个动作的结果..

有些Apache的模块,比如mod_gzip,可能自己进行输出缓存,

这将导致flush()函数产生的结果不会立即被发送到客户端浏览器。

甚至浏览器也会在显示之前,缓存接收到的内容。例如 Netscape

浏览器会在接受到换行或 html 标记的开头之前缓存内容,并且在

接受到 </table> 标记之前,不会显示出整个表格。

一些版本的 Microsoft Internet Explorer 只有当接受到的256个

字节以后才开始显示该页面,所以必须发送一些额外的空格来让这

些浏览器显示页面内容。

所以, 正确使用俩者的顺序是. 先ob_flush, 然后flush,
当然, 在其他sapi下, 不调用flush也可以, 只不过为了保证你代码的可移植性, 建议配套使用.
结论:

php输出缓冲激活后,php会把输出的内容储存在buffer里面,但是如果使用ob_flush,flush 的话则会强制把内容输出到客户端;
输出缓冲的流程:php buffer -> web Server buffer -> 浏览器的buffer->浏览器显示;
有时候无法刷新输出就是因为服务器buffer或者浏览器buffer;

HTTP CHUNK:

Chunk 是 Http 协议的一个编码方式。简单的解释就是“服务器生成HTTP回应是无法确定消息大小的,这时用Content-Length就无法事先写入长度,而需要实时生成消息长度,这时服务器一般采用Chunked编码。在进行Chunked编码传输时,在回复消息的头部有transfer-coding并定为Chunked,表示将用Chunked编码传输内容。”我们可以通过 FireBug 等调试工具查看服务器的 Http 响应头,看到有 transfer-coding 并且值为 Chunked 的,就表明采用了 Chunk 编码。
Chunk 和“分部加载”关系:Http 的 Chunk 编码实际上就是一种将 Http 响应分部传送的方法。一个Http响应可以有若干个Chunk组成,由一个标明长度为0的chunk结束,每个Chunk有两部分组成,第一部分是该Chunk的长度和长度单位(一般不写),第二部分就是指定长度的内容。而当浏览器接收到服务器的响应并判定响应是 Chunk 编码的,则浏览器可以在每接收一个 Chunk 段完毕时先行渲染这个 Chunk 段所携带的内容。这样就实现了“分部加载”的目的。
php案例:

<?php  
   $content = array("我是文章题目", "我是文章简介", "我是章节索引", "我是章节内容",);
   $buffer_size = 4096;
   foreach ($content as $c) {
       echo str_pad( "<p>$c</p>", $buffer_size);   
       ob_flush();                               
       flush();                              
       sleep(1);//我们这里故意放慢节奏,等待一秒 
   }

结果如图所示:

You May Also Like

About the Author: ly_blog

发表评论

电子邮件地址不会被公开。 必填项已用*标注