zoukankan      html  css  js  c++  java
  • 关于PHP 缓冲区

    最权威的资料:http://php.net/manual/en/function.flush.php
    里面有全世界的开发者的留言。常见问题都有讨论。


    再说一下PHP 缓冲区相关的。
    web服务器 如 apache, php.ini配置文件。都有关系。


    If flush() function does not work. You must set next options in php.ini like:


    --[code]--
     output_buffering = Off  
     ;output_handler =   
     zlib.output_compression = Off  
     ;zlib.output_handler =   
    --[^code^]--


    If things does not work you must view headers from the server and check `Server` string.
    In my case, as the frontend was Nginx webserver and Apache work as backend.
    Accordingly, buffering must be disabled in Nginx config file.
    To stop buffering you must add next string to config file:


    --[code]--
    proxy_buffering off;
    --[^code^]--
    -------------------------------------------
    也可以在代码中设置:
    apache_setenv('no-gzip', 1);
    ini_set('zlib.output_compression', 0);
    ini_set('implicit_flush', 1);
    -------------------------------------------


    示例代码:
    ob_end_clean();
    apache_setenv('no-gzip', 1);
    ini_set('zlib.output_compression', 0);
    ini_set('implicit_flush', 1);
    ob_start();//开始缓冲数据
    for($i = 1; $i <= 100; $i++){
        $sourceName = 'filetoupload' . $i;
        $imageArray = array();
        $message = "Image $i has been uploaded to the server<br/>";
        echo $message.str_repeat(" ",1024);//ie有默认的1k buffer
        ob_flush();
        flush();
        usleep(500000);
    }


    首先先来介绍一下相关的几个函数的概念:


    ob_start: 打开输出缓冲区,当缓冲区激活时,所有来自PHP程序的非头文件信息均不会发送,而是保存在内部缓冲区。


    ob_get_contents: 返回内部缓冲区的内容。


    ob_get_clean: 返回内部缓冲区的内容,并关闭缓冲区,(相当于ob_get_contents() and ob_end_clean())。


    ob_get_flush: 返回内部缓冲区的内容,并关闭缓冲区,再释放内部缓冲区的内容。相当于ob_end_flush() 并返回内部缓冲区内容。


    ob_get_lenght: 返回内部缓冲区的长度,如果缓冲区未被激活,该函数返回FALSE。


    ob_clean: 删除内部缓冲区的内容,但不关闭缓冲区,也就是说该语句之后的输出内容将会继续被添加至缓冲区。


    ob_flush: 释放内部缓冲区的内容,并删除内部缓冲区的内容,但不关闭缓冲区。


    flush: 刷新输出缓冲,将ob_flush 释放出来的内容,以及不在PHP 缓冲区的内容,全部输出至浏览器。


    ob_end_clean: 删除内部缓冲区的内容,并关闭缓冲区。


    ob_end_flush: 释放内部缓冲区的内容,并关闭缓冲区。


    (这里只要带flush 都会输出)


    ob_gzhandler: ob_start回调函数,用gzip 压缩缓冲区的内容。


    ob_implicit_flush:  打开或关闭绝对刷新,默认为关闭。所谓绝对刷新,当有输出语句,比如说echo被执行时,便把输出直接发送到浏览器,而不再需要调用flush()或等到脚本结束时才输出。


    注意事项:


    一些Web服务器的output_buffering默认是4069字符或者更大,即输出内容必须达到4069字符服务器才会flush刷新输出缓冲,为 了确保flush有效,最好在ob_flush()函数前有以下语句:
    print str_repeat(“ ”, 4096); //以确保到达output_buffering值。


    ob_* 系列函数是操作PHP本身的输出缓冲区,所以,ob_flush只刷新PHP自身的缓冲区。而flush是刷新apache的缓冲区。所以,正确使用俩者的顺序是:先ob_flush,然后flush。ob_flush是把数据从PHP的缓冲中释放出来,flush是把缓冲内/外的数据全部发送到浏览器。


    不要误认为用了ob_start()后,脚本的echo/print等输出就永远不会显示在浏览器上了。因为PHP脚本运行结束后,会自动刷新缓冲区并输出内容。


    要先ob_start()再 flash否则报错 Message: ob_flush() [ref.outcontrol]: failed to flush buffer. No buffer to flush.


    我们在说说ob_start的用法


    ob_start([string output_callback]):这里可是设置一个回调函数,打开缓冲区之后,所有的输出信息不再直接发送掉浏览器,而是保存在输出缓冲区里面,可以用这个回调函数用于处理输出结果的信息.


    比如:


    function test($str){
        return str_replace('php100','haha',$str);
    }
    ob_start('test');
    echo 'hello php100';
    ob_end_flush();
    在上面的例子中,使用 echo() 的输出内容将会保存在输出缓冲区中,直到调用了 ob_end_flush()或者脚本运行终止, 然后输出信息由自定义的处理函数进行处理(替换里面的字符串)并返回结果。


     


    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()则会静默的清除服务端缓存的数据,而不会有任何数据或其他行为。

  • 相关阅读:
    检测右键点击
    o(∩_∩)o. 原来如此,FLV或者流播放结束的事件不是STOP,而是Complete.
    epoll和selecter
    爬虫与Python:(四)爬虫进阶一之数据抓取——1.Ajax简介
    爬虫与Python:(四)爬虫进阶二之数据存储(文件存储)——1.Text存储
    Python之复制文件目录和快捷方式
    爬虫与Python:(三)基本库的使用——扩展:requests爬取阳光电影网源码
    Python内置函数str()——将对象转换为字符串
    爬虫与Python:(四)爬虫进阶一之数据抓取——2.Python模拟Ajax
    爬虫与Python:(三)基本库的使用——扩展:异常处理中except的用法和作用是什么
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3228765.html
Copyright © 2011-2022 走看看