查阅词典Comet中文是“彗星”的意思,起初我见到这个单词的时候,我就猜想优美名字背后到底是什么呢?他是一种WEB服务器推的应用技术(Server Push)。Server Push就如同它自己的名字一样,将更多华丽的web体验“推”进了我们的视野。有 一些观点 将Comet比作是 Ajax 的接班人,这个观点 我无法苟同,我认为Ajax 与Comet 并不存在取代关系。 从实质上讲 Comet 还是Ajax的应用。
要讲清楚Comet是什么的问题?我不妨将话题扯远点,我们先了解下web开发的历史。
大家一定还记得从前,我们在论坛注册账号,一点了提交按钮,页面就一片空白(服务器在刷新页面,处理提交数据),ie的状态图就不停的转,一个提交按钮一点,页面就再也不能进行其他操作了(因为这里的数据请求和界面操作是同步的)。我们就傻等着服务器处理完数据后返回,以前网速也慢,服务器性能也差。那么这个等待时间就会挑战大家的容忍极限。这个就是Ajax诞生要解决的问题。
其实在Ajax这个名字没有出现的时候,‘Ajax’的应用就已经存在了。那时前辈们就已经在WEB方面为追求更完美的用户体验,为追求异步通信,为追求局部刷新摸索出了一些可重用的方式方法。大致方法有2种:
一种是页面中放入一个隐藏的frame 页面,这个页面有一个表单form对象。而数据的提交,就交给这个 frame 页面。就算是刷新也是这个页面刷新,而这个页面由于是隐藏的或者高度和宽度设置为0的,所以刷新时候用户感觉不到。那么当数据返回的时候也就能够达到局部刷新的效果。而且用户操作的页面不用被卡住,这样也达到异步通信的效果了。这种是比较古老和麻烦的方法。
另外一种和当今的Ajax就很类似了。开发人员开发自己的ActiveX 控件,这个控件的功能基本和现在Ajax 差不多,其实Ajax 大家也可以看成是一个ActiveX 控件,只是各大浏览器都实现了这个ActiveX 控件。所以现在我们开发Ajax应用,不用自己开发这个ActiveX 控件。
Ajax实现了对XMLHTTP对象的封装,这个对象有一系列接口,比较重要的是发送异步数据的接口。
2.那Comet是在什么历史背景下诞生的呢?
当服务器端数据发生变化时,客户端如何即时得到通知呢?这个就是Comet诞生的背景。
1. 传统方法定时刷新,就是隔一个时间段浏览器刷新一次。(没有用户受得了这种方法,服务器也害怕遇到这种事情)
2. 长轮询(long-polling)
Ajax隔一段时间就去服务器查询是否有更新,但是多长时间去查询成了问题。因为性能和即时性造成了严重的反比关系。
3.在前面两种方法被否定后,想到了服务器推送至客户端这种模式,但是web开发客户端是一个浏览器(并不是我们自己控制的GUI客户端)。所以Comet登场,简单说还是利用Ajax与服务器建立http长连接查询是否有数据更新,服务器收到一个连接如果没有数据更新就阻塞这个连接不要返回给客户端,直到有新数据再返回给客户端。Web客户端,发起的连接一旦被返回,或者超时就再次建立http长连接。这样就能保证数据的即时更新,以及尽量减少服务器的计算工作。 2. Comet的一些应用
目前Comet主要应用在一些股票web客户端,以及一些基于web的即时聊天系统中。
比较成熟的框架有Dojo ,Dwr 等一些Ajax框架中实现了该功能。
3. Comet 优、 缺点
3.1 缺点
长期占用连接,丧失了无状态高并发的特点。
server push不会是一个没有副作用的解决方案,是否适合还要仔细权衡。
3.2 优点
Ø 实时性好(消息延时小)
Ø 性能好(能支持大量用户)
4.其他服务器推技术
Comet 只是众多服务器推技术中的一种,目前市面上还有许多其他流行服务器推技术。
4.1 Flash XMLSocket
这种方案实现的基础是:
1. Flash 提供了 XMLSocket 类。
2. JavaScript 和 Flash 的紧密结合:在 JavaScript 可以直接调用 Flash 程序提供的接口。
但此方案的缺点在于:
1. 因为 XMLSocket 没有 HTTP 隧道功能,XMLSocket 类不能自动穿过防火墙;
2. 因为是使用套接口,需要设置一个通信端口,防火墙、代理服务器也可能对非 HTTP 通道端口进行限制;
不过这种方案在一些网络聊天室,网络互动游戏中已得到广泛使 用 。
4.2 Java Applet 套接口
在客户端使用 Java Applet,通过 java.net.Socket 或 java.net.DatagramSocket 或 java.net.MulticastSocket 建立与服务器端的套接口连接,从而实现“服务器推”。
这种方案最大的不足在于 Java applet 需要客户端安装JAVA虚拟机 。
5. 总结
Comet 不存在什么新技术,没有什么神秘可言 。 瓶颈主要集中在web server这一块,一般成熟的 Comet 商业应用都会有一套它自己专用的web server,比如lightstreamer就是这样!
实例解析:
服务端:
$filename = dirname ( __FILE__ ) . ' /data.txt ' ;
$msg = isset ( $_GET [ ' msg ' ]) ? $_GET [ ' msg ' ] : '' ;
if ( $msg != '' )
{
// 写入内容至文件
file_put_contents ( $filename , $msg );
die ();
}
set_time_limit ( 0 );
$lastmodif = isset ( $_GET [ ' timestamp ' ]) ? $_GET [ ' timestamp ' ] : 0 ;
// 取得文件最后修改时间
$currentmodif = filemtime ( $filename );
while ( $currentmodif <= $lastmodif )
{
// 有释放CPU占用率的作用
usleep ( 10000 );
// 清除文件缓存信息
clearstatcache ();
$currentmodif = filemtime ( $filename );
}
// return a json array
$response = array ();
$response [ ' msg ' ] = file_get_contents ( $filename );
$response [ ' timestamp ' ] = $currentmodif ;
echo json_encode( $response );
ob_flush ();
flush ();
?>
客户端:
{
if ( ! WebApp._noerror_)
{
setTimeout(WebApp.WebMain, 5000 );
} else
{
setTimeout(WebApp.WebMain, 10 );
}
WebApp._noerror_ = false ;
}
可以看到不管成功失败都将开始一次新的ajax请求。也就是保持了连接。
使用方法:
1.需要php服务器;
2.开两个不同浏览器即可掩饰效果。
这只是一个介绍原理型demo,请勿商业使用。
DEMO下载