很多应用譬如监控、即时通信、即时报价系统都需要将后台发生的变化实时传送到客户端而无须客户端不停地刷新、发送请求。本文首先介绍、比较了常用的“服务器推”方案,着重介绍了 Comet - 使用 HTTP 长连接、无须浏览器安装插件的两种“服务器推”方案:基于 AJAX 的长轮询方式;基于 iframe 及 htmlfile 的流方式。最后分析了开发 Comet 应用需要注意的一些问题,以及如何借助开源的 Comet 框架-pushlet 构建自己的“服务器推”应用。
将“服务器推”应用在 Web 程序中,首先考虑的是如何在功能有限的浏览器端接收、处理信息:客户端如何接收、处理信息,是否需要使用套接口或是使用远程调用。
客户端呈现给用户的是 HTML 页面还是 Java applet 或 Flash 窗口。如果使用套接口和远程调用,怎么和 JavaScript 结合修改 HTML 的显示。
客户与服务器端通信的信息格式,采取怎样的出错处理机制。
客户端是否需要支持不同类型的浏览器如 IE、Firefox,是否需要同时支持 Windows 和 Linux 平台。
基于客户端套接口的“服务器推”技术
这种方案实现的基础是:
Flash 提供了 XMLSocket 类。
JavaScript 和 Flash 的紧密结合:在 JavaScript 可以直接调用 Flash 程序提供的接口。
2.Java Applet 套接口
在客户端使用 Java Applet,通过 java.net.Socket 或 java.net.DatagramSocket 或 java.net.MulticastSocket 建立与服务器端的套接口连接,从而实现“服务器推”。
基于 HTTP 长连接的“服务器推”技术
1.基于 AJAX 的长轮询(long-polling)方式
2.基于Iframe 及 htmlfile 的流(streaming)方式
Comet
Comet的客户端有基于javascript的cometd-dojox,基于java的cometd-jetty,基于flex的flexcomet。
Server端有基于java的comtd-java和ibm的Feature Pack for Web 2.0。
Comet的主要逻辑如下:
用基于http的长连接来进行消息通信。客户端先向服务器端发送一个httprequest,服务器端接收到后,阻塞在那边,等服务器有消息的时候,则返回一个httpresponse给客户端,客户端收到后,断开连接,紧接着再发第二个httprequeest,以此反复进行,保持这个“长连接”。期间,如果连接超时,那么会断开重连,以保持连接。
Bayeux协议
Bayeux协议是基于Json格式的,client和server直接的发布订阅消息协议。这个协议基于http,允许在普通http情况下,参与者之间的异步消息。
一般情况下,在http协议中,client要想获得server的消息,必须先自己发送一个request,然后server才会给予response。而Bayeux协议改变了这个情况,他允许server端异步push自己的消息到client端。从而实现了client和server之间的双向操作模式(bi-directional communications)。
主要逻辑如下:
Client和server直接先通过握手协议,互相发送request和response进行握手;如果握手成功,那么client再向server发送connect request,server接着发送connect response,如果这步也成功,那么client和server之间的Bayeux协议连接成功。否则,要返回开始重新进行握手协议。
BC ----------------------------------------- BS
| ------------------ handshake request ---> |
| <-- unsuccessful handshake response ----- |
| ------------------ handshake request ---> |
| <-- successful handshake response ------- |
| -------------------- connect request ---> |
~ ~ wait
| <------ connect response ---------------- |
| -------------------- connect request ---> |
| <---- unsucessful connect response ------ |
| ------------------ handshake request ---> |
| <-- successful handshake response ------- |
| -------------------- connect request ---> |
~ ~ wait
| <------ connect response ---------------- |
具体实现的例子
客户端flex comet,服务器ibm的Feature Pack for Web 2.0。
Server 端实现要开启Web messaging service。配置好service integration bus;还要建立一个web messaging的配置文件,里面有bus和轮询超时时间等信息。
Client初始化一个HTTPService,设置url为server端的目标地址。这个地址是server端用来处理连接请求的地址。Feature Pack for Web 2.0里是一个servelet——WebMsgServlet。然后把一个json格式的握手消息,发送到服务器端:
- var handshake:Object = {
- version: "1.0",
- minimumVersion: "0.9",
- channel: BayeuxProtocol.META_HANDSHAKE,
- ext: { "json-comment-filtered": true },
- supportedConnectionTypes: SUPPORTED_CONNECTION_TYPES
- };
然后client端正handshakeHandler里面等待服务器的相应,如果握手失败;那么重新进行握手,如果成功,那么发送json格式的connect消息:
- var connect:Object = {
- channel: BayeuxProtocol.META_CONNECT,
- clientId: _clientId,
- connectionType: BayeuxProtocol.TRANSPORT_LONGPOLLING
- };
连接成功后,client端执行subcribe(),发送subcribe消息到server端,在这里的ch是双方预先定义好的必须一致的topic,如/TOPIC/ABCD
- var subscribe:Object = {
- channel: BayeuxProtocol.META_SUBSCRIBE,
- clientId: _clientId,
- subscription: ch
- };
之后client端和server端的消息会根据channel的格式进行过滤,把不符合meta channe和topic channel的消息通通滤掉。
基本的流程就这样了。
【参考】
1. IBM doc about Web Message Service(we use it) http://publib.boulder.ibm.com/infocenter/wsdoc400/v6r0/index.jsp?topic=/com.ibm.websphere.webmsg.help/docs/QuickStart.html
2. Many articles about comet and cometd
3. A website about bayeux protocol.If you want to know deep into this technology ,you'd better to know about bayeux protocol first.
http://svn.xantus.org/shortbus/trunk/bayeux/bayeux.html
4. A website about JSON.The message data is transmitted in JSON format between server and client side.
5. 基于 HTTP 长连接的“服务器推’技术 http://www.ibm.com/developerworks/cn/web/wa-lo-comet/#resources