for($i=0;$i<20;$i++) {
echo $i;
flush();
sleep(1);
}
但是往往服务器并不顺序输出,而是等待一段时间后一次性输出,google一下了解到,这里涉及了ob_flush()、flush()两个函数,ob_* 系列函数是操作PHP本身的输出缓冲区,ob_flush()是把数据从PHP的缓冲中释放出来,flush()是把不在缓冲中的或者说是被释放出来的数据发送到浏览器。即输出的正常流程是:echo->php内部缓存->服务器缓存->浏览器。对应的输出缓存流程是:echo "hello~"->ob_flush()->flush()。所以代码更改为:
for($i=0;$i<20;$i++) {
echo $i;
if(ob_get_length()){
ob_start();
ob_flush();
flush();
ob_end_flush();
}
sleep(1);
}
这里增加了一个缓冲区内容长度判断,相关函数参考如下:
还是无法顺序输出,再google得 php内部缓存一文,
- ob_start : 打开输出缓冲区,当缓冲区激活时,所有来自PHP程序的非文件头信息均不会发送,而是保存在内部缓冲区。
- 获取缓冲区信息
- ob_get_contents : 返回内部缓冲区的内容。
- ob_get_clean : 返回内部缓冲区的内容,并关闭缓冲区。相当于执行 ob_get_contents() and ob_end_clean()
- ob_get_flush :返回内部缓冲区的内容,并关闭缓冲区,再释放内部缓冲区的内容。相当于ob_end_flush() 并返回内部缓冲区内容
- ob_get_length :返回内部缓冲区的长度,如果缓冲区未被激活,该函数返回FALSE。
- ob_get_level: Return the nesting level of the output buffering mechanism
- ob_get_status: Get status of output buffers
- 关闭/删除/刷新缓冲
- ob_clean :删除内部缓冲区的内容,但不关闭缓冲区,也就说该语句之后的输出内容将会继续被添加至缓冲区。
- ob_flush :释放内部缓冲区的内容,并删除内部缓冲区的内容,但不关闭缓冲区。
- flush: 将ob_flush释放出来的内容,以及不在PHP缓冲区中的内容,全部输出至浏览器。
- ob_end_clean :删除内部缓冲区的内容,并关闭缓冲区。
- ob_end_flush :释放内部缓冲区的内容,并关闭缓冲区。
- 其它
- ob_gzhandler: ob_start 回调函数,用gzip压缩缓冲区的内容。
- ob_implicit_flush: 打开或关闭绝对刷新,默认为关闭(但受implicit_flush选项的制约)。所谓绝对刷新,即当有输出语句(e.g. echo)被执行时,便把输出直接发送到浏览器,而不再需要调用 flush()或等到脚本结束时才输出。
- ob_list_handlers :List all output handlers in use
- output_add_rewrite_var: Add URL rewriter values
- output_reset_rewrite_vars — Reset URL rewriter values
一些Web服务器的output_buffering默认是4069字符或者更大,即输出内容必须达到4096字符服务器才会flush刷新输出缓冲,为 了确保flush有效,最好在ob_flush()函数前有以下语句:再测试,ok,看来来我测试用pipni服务器也是这问题,虽然phpinfo得到print str_repeat(" ", 4096); //以确保到达output_buffering值。
output_buffering no value no value但试验得出似乎是这个的问题。于是代码如下:
for($i=0;$i<20;$i++) {
echo $i.'
';
echo str_pad('', 4096);
if(ob_get_length()){
ob_start();
ob_flush();
flush();
ob_end_flush();
}
sleep(1);
}
顺利地顺序输出了:
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
这样php服务端的长连接就可以准备好了~