这段时间在研究web服务器消息推送,除了html5的websocket,comet是一项很好的方案。comet不是一项专门的技术,更像是一个解决方案。说来也简单,服务端需要能把connection hold,浏览器也需要特殊的支持保持从服务端获取数据,幸好用xmlhttprequest,ajax的实现也是靠它。comet一般有两种方式long poll和streaming。长轮询是client发起请求以后,服务端发现没有数据要发给客户端就先hold起来,直到数据要发给client,请求本次请求。客户端需要不断的发起这样的请求。长轮询相比定时发起的短轮询显然能减少对服务器的请求。注意虚线部分有一个close的动作,然后再发起一次请求。
![](http://dl.iteye.com/upload/attachment/0078/9174/4abcf3a3-96a8-3f20-9537-d68ae1ced3da.jpeg)
另外一种方式是streaming,从名字上就看出,他是在建立长连接以后源源不断地从服务端接收数据。而不需要关闭再重现建立。不过这种方式也有点限制Streaming方式需要responseText有内容或者内容不同于上次时触发readyStateReady,IE在内容改变时不会触发readyStateChange,这样就接收不到新的内容。
![](http://dl.iteye.com/upload/attachment/0078/9176/a5761747-92db-3b94-b50e-7193f6bd0caf.jpeg)
Netty对http支持的很好,自带的httpstaticfileserver的例子甚至可用来做来开发环境的静态服务器。
用它来实现comet只是稍加改造的事儿,所以我试着用来实现了一个聊天室的例子,类似jetty的聊天室。想法很理想,实现起来还是遇到了一点问题。
1. 想要源源不断向浏览器写数据,那不能用content-length这样的length header的编码方式,而得用chunked方式。期间深入了解了一下chunked编码的方式。以及在netty中如何使用chunk
2. 开始的设想使用一个长连接接收聊天信息也发送聊天信息 。后来发现这样使不可能。接收信息采用一个长连接,而发送消息采用短链接。
3. xmlhttprequest的readyState状态有5中分别是0-4,2是收到所有的header并解析。3是开始接收body中的内容。在Chrome下运行正常反而在ff下不能好好的运行,后来仔细查看一番firefox的xmlhttprequest的文档发现用错了一个参数multipart,这个参数貌似只在ff下有。
代码也很简单,好多代码都是从tomcat的comet例子中借鉴过来。我打了包放在附件中,感兴趣的可以看看,运行以后打开http://localhost:8080/chat.html访问。代码比较丑乱,注重功能的实现。可以在googlecode上查看http://code.google.com/p/netty-rpc/的cometserverhandler