博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

基于AJAX的长轮询(long-polling)方式实现简单的聊天室程序

(转http://blog.csdn.net/neusoftware_20063500/archive/2009/04/30/4140903.aspx)

 

这里只是做个测试,很简单,没有做好线程同步的问题,只是为了长轮询。

原理:

可以看:http://yiminghe.javaeye.com/blog/294781

AJAX 的出现使得 JavaScript 可以调用 XMLHttpRequest 对象发出 HTTP 请求,JavaScript 响应处理函数根据服务器返回的信息对 HTML 页面的显示进行更新。使用 AJAX 实现“服务器推”与传统的 AJAX 应用不同之处在于:

  1. 服务器端会阻塞请求直到有数据传递或超时才返回。
  2. 客户端 JavaScript 响应处理函数会在处理完服务器返回的信息后,再次发出请求,重新建立连接。
  3. 当客户端处理接收的数据、重新建立连接时,服务器端可能有新的数据到达;这些信息会被服务器端保存直到客户端重新建立连接,客户端会一次把当前服务器端所有的信息取回。

聊天页面的代码:

  1. <%@ page language="java" pageEncoding="GBK"%>  
  2. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  3. <html>  
  4.     <head>  
  5.         <title>chat room</title>  
  6.         <meta http-equiv="pragma" content="no-cache">  
  7.         <meta http-equiv="cache-control" content="no-cache">  
  8.         <meta http-equiv="expires" content="0">  
  9.         <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
  10.         <meta http-equiv="description" content="This is my page">  
  11.         <mce:script type="text/javascript" src="ext-2.2/adapter/ext/ext-base.js" mce_src="ext-2.2/adapter/ext/ext-base.js"></mce:script>  
  12.         <mce:script type="text/javascript" src="ext-2.2/ext-all.js" mce_src="ext-2.2/ext-all.js"></mce:script>  
  13.         <mce:script type="text/javascript"  
  14.             src="ext-2.2/build/locale/ext-lang-zh_CN.js"></mce:script>  
  15.         <mce:script type="text/javascript" src="jslib/mm.js" mce_src="jslib/mm.js"></mce:script>  
  16.     </head>  
  17.     <body>  
  18.         <div id="main"></div><!-- 显示聊天记录的区域 -->  
  19.         username:  
  20.         <input type="text" name="username" />  
  21.         <br>  
  22.         message:  
  23.         <input type="text" id="message">  
  24.         <br>  
  25.         <input type="button" value="submit" onclick="putMsg()">  
  26.     </body>  
  27. </html>  

定义mm.js,定义发送消息,定义接收消息的JS函数

  1. Ext.onReady(function () {  
  2.     getMsg();  
  3. });  
  4. function getMsg() {  
  5.     Ext.Ajax.request({url:"getMsg", callback:function (options, success, response) {  
  6.         if (success) {  
  7.             Ext.DomHelper.append(Ext.get("main"), response.responseText, true);  
  8.         }  
  9.         getMsg();  
  10.     }});  
  11. }  
  12. function putMsg() {  
  13.     Ext.Ajax.request({url:"putMsg", params:{message:document.getElementById("message").value}});  
  14. }  
  15. /* 
  16. Ext.Updater.defaults.indicatorText='<div><img src="icon/loading.gif" mce_src="icon/loading.gif" width="20" height="20"/>refresh...</div>'; 
  17.     var updater = Ext.get('main').getUpdater(); 
  18.     updater.update({ 
  19.         url:"getMsg" 
  20.     }); 
  21. */  

 下面是获得message的servlet

  1. package hyjc.listener;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.PrintWriter;  
  5.   
  6. import javax.servlet.ServletException;  
  7. import javax.servlet.http.HttpServlet;  
  8. import javax.servlet.http.HttpServletRequest;  
  9. import javax.servlet.http.HttpServletResponse;  
  10.   
  11. public class GetMsg extends HttpServlet {  
  12.   
  13.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  14.             throws ServletException, IOException {  
  15.   
  16.         response.setContentType("text/html");  
  17.         PrintWriter out = response.getWriter();  
  18.         MessageList m = MessageList.getInstance();  
  19.         boolean end = false;  
  20.         while (!end) {  
  21.             System.out.println("before get");  
  22.             String msg = m.get();  
  23.             System.out.println("after get " + msg);  
  24.             out.write(msg + "<br>");  
  25.             if (m.isEmpty()) {  
  26.                 end = true;  
  27.             }  
  28.         }  
  29.         out.close();  
  30.     }  
  31.   
  32.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  33.             throws ServletException, IOException {  
  34.         doGet(request, response);  
  35.     }  
  36.   
  37. }  

下面是添加消息的servlet

  1. package hyjc.listener;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.PrintWriter;  
  5.   
  6. import javax.servlet.ServletException;  
  7. import javax.servlet.http.HttpServlet;  
  8. import javax.servlet.http.HttpServletRequest;  
  9. import javax.servlet.http.HttpServletResponse;  
  10.   
  11. public class PutMsg extends HttpServlet {  
  12.   
  13.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  14.             throws ServletException, IOException {  
  15.   
  16.         response.setContentType("text/html");  
  17.         System.out.println("put message");  
  18.         PrintWriter out = response.getWriter();  
  19.         out.flush();  
  20.         String msg = request.getParameter("message");  
  21.         if (null != msg) {  
  22.             MessageList.getInstance().add(msg);  
  23.         } else {  
  24.             System.out.println("添加消息:" + msg + "成果");  
  25.         }  
  26.         out.close();  
  27.     }  
  28.   
  29.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  30.             throws ServletException, IOException {  
  31.         doGet(request, response);  
  32.     }  
  33.   
  34. }  

下面是存放消息的消息队列,内部用阻塞队列使用

  1. package hyjc.listener;  
  2.   
  3. import java.util.Iterator;  
  4. import java.util.concurrent.LinkedBlockingQueue;  
  5.   
  6. public class MessageList {  
  7.   
  8.     private static MessageList list = null;  
  9.   
  10.     private static Object key = new Object();  
  11.   
  12.     private MessageList() {  
  13.         this.add("hello");  
  14.         this.add("world");  
  15.     }  
  16.   
  17.     public static MessageList getInstance() {  
  18.         synchronized (key) {  
  19.             if (list == null) {  
  20.                 list = new MessageList();  
  21.             }  
  22.             return list;  
  23.         }  
  24.     }  
  25.   
  26.     private LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>();  
  27.   
  28.     public boolean isEmpty() {  
  29.         return queue.isEmpty();  
  30.     }  
  31.   
  32.     public int size() {  
  33.         return queue.size();  
  34.     }  
  35.   
  36.     public String get() {  
  37.         try {  
  38.             return queue.take();  
  39.         } catch (InterruptedException e) {  
  40.             e.printStackTrace();  
  41.             return null;  
  42.         }  
  43.     }  
  44.   
  45.     public void clear() {  
  46.         queue.clear();  
  47.     }  
  48.   
  49.     public void add(String msg) {  
  50.         try {  
  51.             queue.put(msg);  
  52.         } catch (InterruptedException e) {  
  53.             e.printStackTrace();  
  54.         }  
  55.     }  
  56.   
  57.     public Iterator<String> iterator() {  
  58.         return queue.iterator();  
  59.     }  
  60. }  

下面是演示效果,输入message,点击submit,就会添加到MessageList中,然后会在GetMsg中继续执行,实现长连接

 

其它相关文章

http://yiminghe.javaeye.com/blog/284953

http://yiminghe.javaeye.com/blog/294781 

http://yiminghe.javaeye.com/blog/300050 

 

posted on 2010-12-03 12:53  Likwo  阅读(11071)  评论(0编辑  收藏  举报