`

用java实现comet,基于HTTP长连接的实现,用于从服务端实时发送信息到客户端

    博客分类:
  • java
阅读更多

 参考文档 http://www.ibm.com/developerworks/cn/web/wa-lo-comet/

 

        comet是HTTP长连接,就是在HTTP发送请求时,服务器不立刻发送响应信息给客户端, 而是保持着连接,等待一定情况发生后才把数据发送回去给客户端。所以用comet可以实现服务器端的数据实时地发送给客户端。

        本文主要是用java和js来简单地实现comet,最后附上源码和使用例子。

        在客户端用XMLRequest发送请求到服务器,在服务器端用一个servlet来接收XMLRequest的请求,当接收到请求时,并不立刻响应客户端,而是把该servlet线程阻塞,等到一定事件发生后,再响应客户端。当客户端接收到服务端的响应后,调用自定义的回调函数来处理服务器发送回来的数据,处理完成后,再发送一个XMLRequest请求到服务端,这样循环下去,就可以实现数据的实时更新,又不必要在客户端不断地轮循(polling)。

         利用该comet的实现(以后简称为keeper)时,只要在客户端注册事件和写一个处理返回数据的回调函数,然后在服务端实现keeper中的EventListener接口,调用Controller.action(eventListener,eventType)就可以了。

        keeper分成两大部分,第一部分为客户端的javascript,第二部分是服务端的servlet和事件处理。

        一.客户端

        建立一个XMLRequest对象池,每发送一次请求,从对象池中取一个XMLRequest对象,如果没有可用的对象,则创建一个,把它加入到对象池中。这部分的代码来自于网络。

        为了使用方便,再添加一些方法,用来注册事件。这样只要调用注册函数来注册事件,并且把回调函数传给注册事件函数就行了,处理数据的事情,交给回调函数,并由用户来实现。

        keeper为了方便使用,把客户端的javascript代码集成在servlet中,当配置好keeper的servlet,启动HTTP服务器时,keeper会根据用户的配置,在相应的目录下生成客户端的javascript代码。

    二.服务端

        服务端的servlet初始化时,根据配置来生成相应的客户端javascript代码。

        servlet的入口由keeper.servlet.Keeper.java中的doGet进入。在Keeper的doGet中,从请求中获取用户注册事件的名称(字符串类型),然后根据事件的名称,构造一个事件(Event类型),再把它注册到NameRegister中,注册完成后,该servlet线程调用wait(),把自已停止。等待该servlet线程被唤醒后,从Event中调用事件的EventListener接口的process(request,response)来处理客户端的请求。

        

  1.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  2.         String eventName = request.getParameter("event");
  3.         NameRegister reg = NameRegister.getInstance();
  4.         Event event = null;
  5.         try {
  6.             event = reg.getEvent(eventName);
  7.             if(event == null) {
  8.                 event = new Event(eventName,this);
  9.                 reg.registeEvent(eventName, event);
  10.             }
  11.             if(event.getServlet() == null) {
  12.                 event.setServlet(this);
  13.             }
  14.             
  15.         } catch (RegistException e1) {
  16.             e1.printStackTrace();
  17.         }
  18.         synchronized(this) {
  19.             while(!event.isProcess()) {
  20.                 try {
  21.                     wait();
  22.                 } catch (InterruptedException e) {
  23.                     e.printStackTrace();
  24.                 }
  25.             }
  26.         }
  27.         EventListener listener = event.getListener();
  28.         if(listener != null) {
  29.            listener.process(request,response);
  30.         }   
  31.     }

        在服务端处理事件时,调用了keeper.control.Controller中的静态方法action(EventListener listener,String eventName)来处理。如下所示。

 

 

  1.     public static boolean action(EventListener listener,String eventName){
  2.         NameRegister reg = NameRegister.getInstance();
  3.         HttpServlet servlet = null;
  4.         Event e = null;
  5.         try {
  6.             e = reg.getEvent(eventName,true);
  7.             if(e == null) {
  8.                 return false;
  9.             }
  10.             e.setListener(listener);
  11.             servlet = e.getServlet();
  12.             e.setProcess(true);
  13.             synchronized(servlet) {
  14.                 servlet.notifyAll();
  15.             }
  16.         } catch (RegistException ex) {
  17.             ex.printStackTrace();
  18.             }
  19.         if(servlet != null && e != null) {
  20.             e = null;
  21.             return true;
  22.         } else {
  23.             return false;
  24.         }
  25.     }

下面开始用keeper来写一个简单的网页聊天程序和基于服务端的时间。

 

 

    1.客户端设置

        注册两个事件,一个用于是时间事件,一个是消息事件。同时还要写两个回调函数,用于处理服务端返回的时间和聊天消息。如下所于:

  1. <script type="text/javascript">
  2.     Keeper.addListener('timer',showTime);//注册时间事件
  3.     function showTime(obj){ //时间处理回调函数
  4.         var sp = document.getElementById("dateTime");
  5.         if(sp){
  6.             sp.innerHTML = obj.responseText;
  7.         }
  8.     }
  9.     function startOrStop(obj){
  10.         var btn = document.getElementById("controlBtn")
  11.         btn.value=obj.responseText;
  12.     }
  13.     Keeper.addListener('msg',showMsg,"GBK");//注册消息事件,最后一个参数是
  14. //字符串编码
  15.     function showMsg(obj){//处理消息的回调函数
  16.         var msg = document.getElementById("msg");
  17.         if(msg){
  18.             
  19.                 msg.value = obj.responseText+"\n"+msg.value;
  20.             
  21.         }
  22.     }
  23.     function sendMsg() {
  24.         var msg = document.getElementById("sendMsg");
  25.         if(msg){
  26.             var d = "msg="+msg.value;
  27.             sendReq('POST','./demo',d,startOrStop);
  28.             msg.value = "";
  29.         }
  30.     }
  31.     
  32. </script>

    2.配置服务端

    服务端的配置在web.xml文件中,如下所示

  1.   <servlet>
  2.     <servlet-name>keeper</servlet-name>
  3.     <servlet-class>keeper.servlet.Keeper</servlet-class>
  4.     <init-param>
  5. <!--可选项,设置生成客户端的JavaScript路径和名字,默认置为/keeper.js-->
  6.       <param-name>ScriptName</param-name>
  7.       <param-value>/keeperScript.js</param-value>
  8.     </init-param>
  9. <!--这个一定要设置,否则不能生成客户端代码-->
  10.     <load-on-startup>1</load-on-startup>
  11.   </servlet>
  12.   <servlet-mapping>
  13.     <servlet-name>keeper</servlet-name>
  14.     <url-pattern>/keeper</url-pattern>
  15.   </servlet-mapping>

 

        用<script type="text/javascript" src="./keeperScript.js"></script>在页面包含JavaScript时,这里的src一定要和上面配置的一至。上面的设置除了<init-param></init-param>为可选的设置外,其他的都是必要的,而且不能改变。

 

 

        3.编写事件处理代码,消息的处理代码如下:

    

  1.     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  2.         System.out.println("Post..");
  3.         String msg = request.getParameter("msg");
  4.         Controller.action(new SendMsg(msg),"msg");
  5.     }

  1. class SendMsg implements EventListener{
  2.     private String msg;
  3.     public SendMsg(String msg) {
  4.         this.msg = msg;
  5.     }
  6.     @Override
  7.     public void process(HttpServletRequest request, HttpServletResponse response) {
  8.         response.setCharacterEncoding("UTF-8");
  9.         PrintWriter out = null;
  10.         try {
  11.             out = response.getWriter();
  12.             if(msg!=null){
  13.                 out.write(msg);
  14.             }
  15.         } catch (IOException e) {   
  16.             e.printStackTrace();
  17.         }
  18.         finally{
  19.             if(out != null) {
  20.                 out.close();
  21.             }
  22.         }       
  23.     }
  24. }

 

 

 到这时,一个基本的keeper应用就完成了。其它部分请参考附件中的例子源码。

分享到:
评论
10 楼 jiang_xiaohan 2012-10-31  
demo是eclipse开发的吗,没打包要重新部署啊
9 楼 itcyt 2012-08-20  
貌似程序跑不了
8 楼 fhp0917 2009-10-26  
IE不支持ajax的长连接
7 楼 朗拿颠老 2009-10-14  
长时间不响应不会超时吗?
6 楼 朗拿颠老 2009-10-14  
谁知道webQQ 浏览器和server长连接原理??是不是和这个一样用阻塞?
5 楼 fzfx88 2009-10-14  
跑了一下程序,比较精辟,收益匪浅。。。

谢谢分享。。。
4 楼 czx566 2008-12-15  
homelink 写道
czx566 写道

推荐TIBCo的 AMS 简单~

是TIBCo EMS(TIBCO Enterprise Message Service)吗?

不好意思,我以为AMS是开源的~因为GI是开源的
但刚才我问了AMS非开源~

所以我现在不推荐AMS~

不是EMS
3 楼 homelink 2008-12-15  
czx566 写道

推荐TIBCo的 AMS 简单~

是TIBCo EMS(TIBCO Enterprise Message Service)吗?
2 楼 czx566 2008-12-15  
推荐TIBCo的 AMS

简单~
1 楼 flypeace 2008-12-15  
刚跑过demo,发现在firefox里面可以,在ie6和ie7都不可以,好象js发送功能在ie里面不管用了

相关推荐

    comet4j使用方法

    Comet4J 是一个专为Java开发者设计的Comet技术框架,它允许服务器与客户端进行实时的双向通信,实现持久连接。Comet技术是解决Web应用程序实时性问题的一种方法,通过长时间保持HTTP连接来实现实时数据推送。下面将...

    SSH整合comet即时通信

    3. **Comet服务端实现**:在服务器端,你需要实现一个Comet处理器,该处理器会在接收到客户端连接后保持这个连接,直到有新的消息需要发送。这个处理器可以是基于Servlet的,如Atmosphere或Jetty的Continuation API...

    WebSocket客户端和服务端实例源码

    用java实现的服务端 Websocket与服务器的正常通信 众所周知,Web 应用的交互过程通常是客户端通过浏览器发出一个请求,服务器端接收请求后进行处理并返回结果给客户端,客户端浏览器将信息呈现,这种机制对于信息...

    comet4j整套开发包最新版

    Comet4j是一种基于Java的服务器推送技术,它允许服务器主动向客户端发送数据,而无需客户端不断轮询请求。在Web应用中,这种技术能够显著提高实时性,尤其是在实时聊天、股票更新、在线游戏等场景中表现优异。该...

    java websocket

    这种客户端是主动方,服务端是被动方的传统Web模式 对于信息变化不频繁的Web应用来说造成的麻烦较小,而对于涉及实时信息的Web应用却带来了很大的不便,如带有即时通信、实时数据、订阅推送等功能的应 用。...

    原创nio socket mina+javascript+flash实现commet长连接网页聊天室

    "原创nio socket mina+javascript+flash实现commet长连接网页聊天室"揭示了一个基于Java NIO(Non-blocking I/O)的Socket通信框架Mina与JavaScript、Flash技术结合,实现COMET(Comet是使服务器向浏览器推送数据的...

    comet4j可运行demo

    Comet4j是一款开源的Java库,专门用于实现服务器向客户端的实时数据推送技术,它基于 comet 模式,能够高效地处理长连接,使得Web应用程序可以即时地将信息推送到客户端,而不仅仅是响应客户端的请求。这个"comet4j...

    Comet4J服务器端推送技术

    它分为服务端与客户端两部分,你只要将服务器端(JAR文件,目前仅支持Tomcat6、7)放入WEB-INF\lib,客户端(JavaScript文件)引入到页面,那么你的应用就具备了向客户端推送信息的能力,而你仅需要在服务器端调用Comet4...

    服务器推送pushlet讲解

    1. Pushlet服务器:这是Comet服务的实现,负责接收客户端连接并保持连接打开状态,直到有新的数据可推送到客户端。 2. Pushlet客户端:通常是一个JavaScript或Java小程序,它连接到Pushlet服务器并接收推送的数据。...

    C#消息推送源码

    2. **Comet**:Comet是一种Web编程模型,用于实现服务器到客户端的长连接,使得服务器能向客户端实时推送数据。在C#中,可以通过建立持久HTTP连接或使用WebSocket等技术来模拟Comet模型。这种技术对于需要实时更新的...

    JAVA消息推送源程序

    消息推送技术是指服务器主动向客户端发送信息的技术,常见的有长轮询(Long Polling)、WebSocket以及Comet等。 - **长轮询(Long Polling)**:客户端发起HTTP请求后,服务器保持连接直到有新消息到达才返回响应。这种...

    AJax,java即时通讯 web qq

    【标题】"AJax,java即时通讯 web qq"揭示了一个基于Web技术实现的即时通讯系统,该系统利用Ajax和Java技术来模拟QQ的聊天功能。Ajax(Asynchronous JavaScript and XML)是一种在无需重新加载整个网页的情况下,...

    Pushlet学习(二) -- Pushlet CookBook部分翻译 + 注释

    Pushlet是基于HTTP的 Comet 模式的实现,Comet是一种服务器向浏览器推送数据的技术,通过长时间保持一个HTTP连接来实现实时通信。Pushlet的核心思想是在服务器端维持一个开放的HTTP连接,直到有新的数据需要发送给...

    websocket构建实时web应用

    - **Websocket定义**:Websocket是一种在单个TCP连接上进行全双工通信的协议,它允许客户端和服务端之间的双向数据交换,这使得实现实时交互成为可能。 - **Websocket与HTTP的关系**:虽然Websocket与HTTP都基于TCP...

    PushMessage JavaWeb聊天 推送 实现

    JavaWeb聊天推送实现主要涉及到的是实时通信技术,用于在服务器和客户端之间传递消息,使得用户能够在不刷新页面的情况下接收到新的信息。在这个场景下,"PushMessage"通常指的是服务器主动向客户端推送数据,而非...

    dwr实现服务器推技术,兼容低版本IE

    DWR(Direct Web Remoting)是一种Java技术,用于在浏览器和服务器之间实现双向通信,即Ajax的增强版,允许服务器主动向客户端推送数据,而无需客户端发起请求。这个技术尤其适用于需要实时更新数据的Web应用,比如...

    DWR服务器推送技术实现WebQQ

    DWR引入了“心跳”机制和“反向AJAX”(Comet)技术,实现了服务器向客户端的实时推送。当服务器有新消息时,会主动将消息推送到已连接的客户端,而不是等待客户端发起请求。 ### 2. DWR服务器推送实现步骤 - **...

    Node.js实现数据推送

    场景:后端更新数据推送到客户端...2. Comet的概念是长连接,客户端发送请求后,后端将连接保持下来,直到连接超时或后端返回数据时再重新建立连接,有效的将通信资源转移到了服务器上,实际消耗的是服务器资源。 3. W

    web聊天室源码 支持单对单聊天 单对多聊天

    6. **Comet技术**:压缩包中的“CometDemo”可能是指Comet技术,这是一种处理服务器推送的旧方法,通过长时间保持HTTP连接来实现实时通信。虽然WebSocket现在更为流行,但Comet在某些情况下仍有一定的应用。 7. **...

    使用WebSocket实现即时通讯(一个群聊的聊天室)

    但是,这些方法都有其缺陷,例如轮询技术要求客户端以设定的时间间隔周期性地向服务端发送请求,频繁地查询是否有新的数据改动,导致过多不必要的请求,浪费流量和服务器资源。 WebSocket的工作流程是这样的:...

Global site tag (gtag.js) - Google Analytics