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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于AJAX的长轮询(long-polling)方式实现简单的聊天室程序相关的知识,希望对你有一定的参考价值。

原理:

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

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

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

技术分享

聊天页面的代码:

   技术分享

 

定义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.getElementByIdx_x_x("message").value}});  
  14. }  
  15.   

 

 下面是获得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 + "
    ");  
  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 queue = new LinkedBlockingQueue();  
  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 iterator() {  
  58.         return queue.iterator();  
  59.     }  
  60. }  

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

技术分享

以上是关于基于AJAX的长轮询(long-polling)方式实现简单的聊天室程序的主要内容,如果未能解决你的问题,请参考以下文章

Libevent + Comet(长轮询/Http-Stream)

反向Ajax,实现服务器向客户端推送消息之 Comet

两个轮询之间的长轮询客户端“时间间隔”

Ajax 长轮询

基于ajax与msmq技术的消息推送功能实现

普通 ajax 和长轮询之间的区别