采用PHP实现”服务器推”技术的聊天室

传统的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打开,看看你看到了什么。

原文链接: http://www.laruence.com/2008/04/16/118.html

原文地址:https://www.cnblogs.com/wwlww/p/8413327.html

时间: 2024-11-07 16:09:22

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

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

public class Content : System.Web.UI.Page{private void Page_Load(object sender, System.EventArgs e){Session.Timeout = 60;Response.Write("欢迎 . . .<br> ");Response.Flush();Application[Session.SessionID] = Response;System.Threading.Thread.Sle

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

“服务器推”技术的应用 传统模式的 Web 系统以客户端发出请求.服务器端响应的方式工作.这种方式并不能满足很多现实应用的需求,譬如: 监控系统:后台硬件热插拔.LED.温度.电压发生变化: 即时通信系统:其它用户登录.发送信息: 即时报价系统:后台数据库内容发生变化: 这些应用都需要服务器能实时地将更新的信息传送到客户端,而无须客户端发出请求.“服务器推”技术在现实应用中有一些解决方案,本文将这些解决方案分为两类:一类需要在浏览器端安装插件,基于套接口传送信息,或是使用 RMI.CORBA 进

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

原文链接:http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ 很多应用譬如监控.即时通信.即时报价系统都需要将后台发生的变化实时传送到客户端而无须客户端不停地刷新.发送请求.本文首先介绍.比较了常用的“服务器推”方案,着重介绍了 Comet - 使用 HTTP 长连接.无须浏览器安装插件的两种“服务器推”方案:基于 AJAX 的长轮询方式:基于 iframe 及 htmlfile 的流方式.最后分析了开发 Comet 应用需要注意的一些问题

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

转自:http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ 很多应用譬如监控.即时通信.即时报价系统都需要将后台发生的变化实时传送到客户端而无须客户端不停地刷新.发送请求.本文首先介绍.比较了常用的“服务器推”方案,着重介绍了 Comet - 使用 HTTP 长连接.无须浏览器安装插件的两种“服务器推”方案:基于 AJAX 的长轮询方式:基于 iframe 及 htmlfile 的流方式.最后分析了开发 Comet 应用需要注意的一些问题,以

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

转载自http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ “服务器推”技术的应用 传统模式的 Web 系统以客户端发出请求.服务器端响应的方式工作.这种方式并不能满足很多现实应用的需求,譬如: 监控系统:后台硬件热插拔.LED.温度.电压发生变化: 即时通信系统:其它用户登录.发送信息: 即时报价系统:后台数据库内容发生变化: 这些应用都需要服务器能实时地将更新的信息传送到客户端,而无须客户端发出请求.“服务器推”技术在现实应用中有一些解决

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

反向 ajax 又叫 comet / server push / 服务器推技术 应用范围:网页聊天服务器,例如新浪微博在线聊天.google mail 网页聊天 原理:一般而言,HTTP 协议的特点是,连接之后断开连接(服务器响应 Content-Length,收到了指定 Length 长度的内容时,也就断开了).在 HTTP 1.1 协议中,允许不写 Content-Length,比如要发送的内容长度确实不知道,此时需要一个特殊的 Content-Type:chunked,叫做分块传输,只有当

Asp.net的服务器推技术 (Server Push)

在以往的和服务器端通信技术中,我们多数使用的是AJAX轮询式访问,也就是在Javascript中控制时间间隔,然后每隔一段时间就访问一次服务器,然后获得数据或通知.但是这种轮询方式的访问有90%是在做无用功.  要想长时间保持服务器和浏览器之间的连接怎么办?长连接技术,这可不是什么新技术,用IFrame作为隐藏帧指向长请求页面的方法早已被很多人运用在互联网上,但是IFrame作为隐藏帧有一个弊端,那就是浏览器的进度条始终处在读取状态.为了使用户获得更好体验,“Google的天才们”使用了一个叫“

comet(基于http长连接的“服务器推”技术)

comet(基于http长连接的“服务器推”技术)web服务器是被动发送数据给客户端的,客户端有请求,服务器端才会响应(发送数据),所以“服务器推”技术加了引号.实现方式有两个:1.基于ajax的长轮询(long-polling)方式 浏览器发送ajax请求(设置timeout,并且对返回的状态进行处理, 猜想:设置了timeout,connection:keep-alive就会加入到请求头中,即基于http长连接), 如果到了时间,http连接断了(底层是tcp连接断了)则重新发起请求.2.基

以C#编写的Socket服务器的Android手机聊天室Demo

 内容摘要  1.程序架构    2.通信协议    3.服务器源代码    4.客户端源代码    5.运行效果  一.程序架构 在开发一个聊天室程序时,我们可以使用Socket.Remoting.WCF这些具有双向通信的协议或框架.而现在,我正要实现一个C#语言作为服务器端.Android作为客户端的聊天室.由于服务器端和客户端不是同一语言(C#和java),所有我选择了Socket作为通信协议. 图1.1所示,我们可以看出:android手机客户端A向服务器端发送消息,服务器端收到消息后,