主题列表:
COMET彗星(一)SERVER PUSH介绍
引言:
在上一篇随笔中,对COMET的机制和原理做了简短的介绍。网上的确有很多类似的资料可以查看,基于PHP,JSP,.NET的框架更是层出不穷。本文将简要介绍并分析一个基于.NET的SERVER PUSH框架,实现了从消息的发布,广播,到接收等一系列SERVER PUSH关键技术。
COMET技术要点:
COMET的理念是先进而直接的,从服务器发布信息,同时让浏览器(也可以是客户端)接收并响应消息事件。就是这样简单的理念,造成了系统设计上的多重麻烦。
首先就是如何让我们的浏览器接收到服务器发来的事件呢?
有一种实现方式是借由无实体大小的FLASH,IFRAME或者APPLET等组件来间接打通客户端SOCKET,然后向这些元件中推入信息,并通过javascript线程,得到元件返回的信息(当然也有极个别情况下,由这些元件来直接向页面注入信息)。
从最终结果看,我们好似得到了一个服务器的稳定连接,并刷新了页面信息。但是实际上,这样的实现方式实在是有点不够“直接”。
FLASH(或FLEX)本身可以通过WEBSERVICE组件调用WSDL,或者直接调用java serverlet,这是FLASH PLAYER给我们的便利条件,但通过FLASH通讯的办法来实现SERVER PUSH总是让人觉得无法接受,为何不直接做一个FLASH通讯呢。
APPLET更不用说,直接将JAR包“推”到页面运行,启动麻烦的JRE的同时还要下载庞大的JAVA程序。没有JRE的情况下,还需要相应下载。
SILVER LIGHT的机制与FLASH类似,那是由于并没有FLASH PLAYER普及,用户同样需要下载相应播放器。
以上三者实在谈不上是完全的web应用,我们只是想用最纯粹的javascript和html来解决问题,又何必劳师动众呢?单纯的javascript事件和线程,难道就不能满足我们的需要么?
于是又有人想到了IFRAME,通过一个隐形的IFRAME来发送AJAX请求,通过长轮询得到消息。但这也不是真正意义上COMET,顶多是一个不成熟的AJAX应用。
COMET的精髓就在于用服务器与javascript来维持浏览器的长连接,同时完成服务器端事件的浏览器端响应。这样的事件广播机制是跨网络的,同时也是实时的。
COMET技术难点:
1.维持长连接
2.维持服务器端的“心跳”
3.浏览器端对“心跳”的“感应”
4.维持长连接与超时的平衡
5.线程同步
6.通用的接口设计
PS:这里需要注意的是,我们是在说COMET技术,而不是在谈论如何找女朋友。虽然从某个角度来看这二者似乎存在着很多类似的地方……
.NET下的COMET实现:
我们需要COMET,我们需要源码,我们需要最单纯的实现。本着这三点需求,我为大家准备了以下这个例子,James Simpson的基于COMET技术的.NET IM。
图1.1 COMET基类类图
实体类:
1.CometClient: COMET的服务实体,实例化一个CometClinet的意义在于记录必要的服务信息,比如用户名称超时设置等。
2.CometMessage: 包含对服务信息和相信属性的实体类,是消息传输的主体。
3.InProcCometStateProvider:继承了ICometStateProvider并实现了消息操作的方法,同时将消息保存在内存中。
接口类:
1.ICometStateProvider: 定义了一系列的接口来提供对CometClient实体和CometMessage的操作。
异常类:
1.CometException: 没有什么特殊的异常类。
事件:
1.CometClientEventHandler: CometClient的事件监听类和广播类。
线程相关:
1.CometWaitThread: 服务器端线程池,排队等待信息请求并调用,同时提供超时等操作。
2.CometWaitRequest: 服务器端线程,监听客户端的message请求。
3.CometAsyncResult: 异步请求的管理类,通过继承SYSTEM.IAsyncResult来实现异步。
主体:
1.CometStateManager: 用来管理线程池,管理线程和用户连接,消息转发等一系列操作的工厂类。
ps:从某种意义上来说,这个例子最好的地方就是在于它的CometStateManager实现是可以被拓展的,定制自己的管理模式,定制自己的存储操作等都可以通过这个类来进行扩展。线程管理在这个DEMO里做得相对成熟,而且事件机制可以通过定制Adapter更加丰富。
由于时间有限,下一篇随笔中将介绍几个关键类的具体实现,和一些关于设计模式的思考。年末了,希望园子里的朋友们都过个收获满满的年。