传统的B/S结构的应用程序,都是采用”客户端拉”结束来实现客户端和服务器端的数据交换。

本文将通过结合Ticks(可以参看我的另外一篇文章:关于PHP你可能不知道的-PHP的事件驱动化设计),来实现一个服务器推的PHP聊天室简单构想。

PHPer,尤其是用过set_cookie, header的,一定见过这样的提示信息:”Warning: Cannot modify header information – headers already sent by…..”, 这是因为通过HTTP协议通信,数据包会包含俩个部分,一个是Header,一个是data。一般来说,都是先Header部分,在Heaer部分指明了 Data部分的长度,然后使用\r\n\r\n来表示header部分结束,接下来是Data部分。

当我们有任何输出的时候,Header部分就发送了,这个时候,你再想header函数来改变一些Header部分的域信息,就会得到上面的提示信息。

一个简单的办法就是使用output_buffering。让它来缓存服务器的输出,不要太早将Header部分发给客户端。

那么,如果不使用output_buffering,是不是就可以实现,每当服务器有输出,就立即发送给客户端呢?

做个如下试验:

//设置php.ini中output_buffering=0 或者使用ob_end_flush()关闭缓存

  1.  
    set_time_limit(0);
    for($i=0;$i<10;$i++){
      echo "Now Index is :". $i;
      sleep(1);
    }
     

结果我们发现,还是要等到脚本全部执行完以后,才能一次看到所有的结果。。

为什么呢?

这是因为我们只是解决了缓存问题,但是还有一个缓冲问题,PHP会缓冲程序的输出。所以,这个时候,我们还需要调用,flush(), 来强制使得PHP将所有的程序输出发送给客户端。

  1.  
    set_time_limit(0);
    //设置php.ini中output_buffering=0
    ob_end_flush();//关闭缓存
     
    set_time_limit(0);
    for($i=0;$i<10;$i++){
      echo "Now Index is :". $i;
      flush();
      sleep(1);
    }
     

现在是不是看到了,不断有服务器的数据显示出来(如果看不到, 可以在输出前填充相当数量的占位字符)?

有几个概念之间的关系,我这里补充以下:

在代码中使用ob_start(), 就相当于在php.ini中使用output_buffering=on一样,使用服务器缓存。

在代码中使用ob_end_flush() 就相当于在php.ini中使用output_buffering = false一样,关闭服务器缓存.

基于前面的讨论,我们就有可能使用Ticks来实现,一个无刷新,无ajax的聊天室: 页面中包含俩个iframe,一个是不断获取聊天室的聊天内容,一个包含用户发表聊天内容的form. 这样,在第一个frame的脚本中:

  1.  
    ob_end_clean();//关闭缓存
  2. set_time_limit(0);
    ob_implicit_flush(); //这个语句将强制每当有输出就自动刷新,相当于在每个echo后,调用ob_flush()
    $new_mesg = NULL;
    register_tick_function("getNewMesg");
    declare(ticks=1){
      while(1){
         if(!is_null($new_mesg)){
              foreach($new_mesg as $msg){
                    echo $msg;
              }
              $new_mesg = null;
         }
      }
    }
     
    function getNewMesg(){
    //通过查询数据库,或者共享内存,来获取现在的聊天室大厅的内容。
    //返回一个数组,包含所有的新的聊天内容
    }
     

这样就实现了一个简单的使用服务器推技术的聊天室的框架。

当然,关于实时输出,还有一些其他的限制,比如在PHP5手册中讲到的:

个别web服务器程序,特别是Win32下的web服务器程序,在发送结果到浏览器之前,仍然会缓存脚本的输出,直到程序结束为止。

有些Apache的模块,比如mod_gzip,可能自己进行输出缓存,这将导致flush()函数产生的结果不会立即被发送到客户端浏览器。

甚至浏览器也会在显示之前,缓存接收到的内容。例如 Netscape 浏览器会在接受到换行或 html 标记的开头之前缓存内容,并且在接受到

标记之前,不会显示出整个表格。

一些版本的 Microsoft Internet Explorer 只有当接受到的256(甚至更多)个字节以后才开始显示该页面,所以必须发送一些额外的空格来让这些浏览器显示页面内容。

接下来,我贴一个很有趣的代码,有兴趣的同学,可以试试:

  1.  
    header("Content-type: multipart/x-mixed-replace;boundary=endofsection");
    print "--endofsection\n";
    $pmt = array("-", "\\", "|", "/" );
    for( $i = 0; $i <10;$i ++ )
    {
            sleep(1);
            print "Content-type: text/plain\n\n";
            print "Part $i     ".$pmt[$i % 4];
            print "--endofsection\n";
            ob_flush(); //强制将缓存区的内容输出
            flush(); //强制将缓冲区的内容发送给客户端
    }
    print "Content-type: text/plain\n\n";
    print "The end\n";
    print "–endofsection–\n";
     

使用firefox打开,看看你看到了什么。

采用PHP实现”服务器推”技术的聊天室的更多相关文章

  1. 如何使用ASP.NET开发基于推技术的聊天室?

    public class Content : System.Web.UI.Page{private void Page_Load(object sender, System.EventArgs e){ ...

  2. Comet:基于 HTTP 长连接的“服务器推”技术

    “服务器推”技术的应用 请访问 Ajax 技术资源中心,这是有关 Ajax 编程模型信息的一站式中心,包括很多文档.教程.论坛.blog.wiki 和新闻.任何 Ajax 的新信息都能在这里找到. c ...

  3. 转载:Comet:基于 HTTP 长连接的“服务器推”技术

    转自:http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ 很多应用譬如监控.即时通信.即时报价系统都需要将后台发生的变化实时传送到客户端而无须客 ...

  4. [转载] Comet:基于 HTTP 长连接的“服务器推”技术

    转载自http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ “服务器推”技术的应用 传统模式的 Web 系统以客户端发出请求.服务器端响应的方式工 ...

  5. “服务器推”技术【转载+整理】

    原文地址 本文内容 "服务器推(server-push)"技术的应用 基于客户端套接口的"服务器推"技术 基于 HTTP 长连接的"服务器推" ...

  6. Comet:基于 HTTP 长连接的“服务器推”技术(转载)

    “服务器推”技术的应用 传统模式的 Web 系统以客户端发出请求.服务器端响应的方式工作.这种方式并不能满足很多现实应用的需求,譬如: 监控系统:后台硬件热插拔.LED.温度.电压发生变化: 即时通信 ...

  7. 【转】Comet:基于 HTTP 长连接的“服务器推”技术

    原文链接:http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ 很多应用譬如监控.即时通信.即时报价系统都需要将后台发生的变化实时传送到客户端而无 ...

  8. Comet:基于 HTTP 长连接的“服务器推”技术解析

    原文链接:http://www.cnblogs.com/deepleo/p/Comet.html 一.背景介绍 传统web请求,是显式的向服务器发送http Request,拿到Response后显示 ...

  9. HTTP 笔记与总结(9)分块传输、持久链接 与 反向 ajax(comet / server push / 服务器推技术)

    反向 ajax 又叫 comet / server push / 服务器推技术 应用范围:网页聊天服务器,例如新浪微博在线聊天.google mail 网页聊天 原理:一般而言,HTTP 协议的特点是 ...

随机推荐

  1. webApi前端ajax调用后端返回{"readyState":0,"status":0,"statusText":"error"}解决方案

    var url = data.url, params = data.params, try_times = data.try_times , async = data.sync == 'false' ...

  2. selenium获取缓存数据

    爬虫呢有时候数据方便有时候登入获得cookies,以及获取他存缓存中的数据 一.获取缓存中的数据其实很简单js注入就好了 localStorage_1 = driver.execute_script( ...

  3. Spring-Security无法正常捕捉到UsernameNotFoundException异常

    前言 在Web应用开发中,安全一直是非常重要的一个方面.在庞大的spring生态圈中,权限校验框架也是非常完善的.其中,spring security是非常好用的.今天记录一下在开发中遇到的一个spr ...

  4. 康托展开+反向bfs

    康托展开+反向bfs hdu 1043 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1043 #include <iostream> # ...

  5. 2018 IEEE极限编程大赛 题解

    去年742,今年72,也算一种小小的进步. 明年前30(笑 1. Drawing Rooted Binary Trees 给定一个树的中序和前序的遍历,要求输出这棵树(包括空格的) #include ...

  6. 安装TensorFlow失败

    ERROR: Could not find a version that satisfies the requirement tensorflow==2.1.0 (from versions: non ...

  7. 用idea打包maven项目

    利用idea工具打包项目 1.点击图中标记①,idea会自动生成打包命令,这个打包命令会包含单元测试内容,如果单元测试的内容报错,是打包不成功的,这个时候我们需要在打包命令中用 -Dmaven.tes ...

  8. 聊聊智能指针 auto_ptr、shared_ptr、weak_ptr和unique_ptr

    本文为转载:https://www.cnblogs.com/zeppelin5/p/10083597.html,对作者有些地方做了修正. 手写代码是理解C++的最好办法,以几个例子说明C++四个智能指 ...

  9. Jenkins-Publish Over SSH插件

    插件安装 打开Jenkins的“系统管理>管理插件”,选择“可选插件”,在输入框中输入“Publish over SSH”进行搜索,如果搜索不到可以在“已安装”里确认是否已经安装过.在搜索结果中 ...

  10. 关于Java8中的Comparator那些事

    在前面一篇博文中,对于java中的排序方法进行比较和具体剖析,主要是针对 Comparator接口和 Comparable接口,无论是哪种方式,都需要实现这个接口,并且重写里面的 方法.Java8中对 ...