`
xiaomao1027
  • 浏览: 9899 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
最近访客 更多访客>>
社区版块
存档分类
最新评论

Comet基于iframe的服务器推送(Server Push)例子

    博客分类:
  • java
阅读更多

Comet基于iframe的服务器推送(Server Push)例子

文章分类:Web前端

    服务器推送技术(Server Push)是最近Web技术中最热门的一个流行术语,它的别名叫Comet(彗星)。它是继AJAX之后又一个倍受追捧的Web技术。Comet有时也称反向 Ajax 或服务器端推技术(server-side push)。其思想很简单:将数据直接从服务器推到浏览器,而不必等到浏览器请求数据。听起来简单,但是如果熟悉 Web 应用 程序,尤其是 HTTP 协议,那么您就会知道,这绝不简单。实现 Comet 风格的 Web 应用程序,同时保证在浏览器和服务器上的可伸缩性,这只是在最近几年才成为可能。目前一些主流网站都有类似的原理,例如:webQQ、开心网、白社会等等,它们中消息动态都是采用类似的技术,也许具体实现方式不一样。目前大概有三种实现方式:基于长轮询(long polling)、基于iframe“、基于流(stream)三种实现comet的方式。
     下面是在Tomcat6.x的基础上实现基于iframe的comet聊天室:

    index.jsp:聊天室页面
    ChatServlet.java:实现了长连接的Servlet
    MessageServlet.java:消息接受Servert

     仅仅是一个Demo,可以从index.jsp?name=yourNickName进入,实现了上线,下线通知,群发,消息功能,性能还没有测试...
     目前能够正常在IE,FireFox和Chrome下正常运行,但在Chrome下会一直加载不完,不知道有没有办法解决?还有不知道能不能在此基础之上搞一个基于iframe的Comet工具,包括前台js和后台java.

     首先修改Tomcat配置文件
      修改server.xml中<Connector connectionTimeout="20000" port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" redirectPort="8443"/>,底层用NIO实现的Http连接器。如果是在Eclipse中运行例子,需要修改Servers下的Tomcat v6.0-config中的server.xml.


index.jsp
Java代码 复制代码
  1.      <%@ page language="java" contentType="text/html; charset=UTF-8"  
  2.     pageEncoding="UTF-8"%>   
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">   
  4. <html>   
  5. <head>   
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">   
  7. <script type="text/javascript" src="jquery-1.4.2.min.js"></script>   
  8. <link rel="stylesheet" href="960.css" />   
  9. <title>Comet Chat Demo</title>   
  10. <script type="text/javascript">   
  11. var server = 'http://localhost:8080/CometDemo/ChatComet?name=<%=request.getParameter("name")%>';   
  12.   
  13. var comet = {   
  14.     connection   : false,   
  15.     iframediv    : false,   
  16.   
  17.     initialize: function() {   
  18.         if (navigator.appVersion.indexOf("MSIE") != -1) {   
  19.             comet.connection = new ActiveXObject("htmlfile");   
  20.             comet.connection.open();   
  21.             comet.connection.write("<html>");   
  22.             comet.connection.write("<script>document.domain = '"+document.domain+"'");   
  23.             comet.connection.write("</html>");   
  24.             comet.connection.close();   
  25.             comet.iframediv = comet.connection.createElement("div");   
  26.             comet.connection.appendChild(comet.iframediv);   
  27.             comet.connection.parentWindow.comet = comet;   
  28.             comet.iframediv.innerHTML = "<iframe id='comet_iframe' src='"+server+"'></iframe>";   
  29.   
  30.         } else if (navigator.appVersion.indexOf("KHTML") != -1) {   
  31.             comet.connection = document.createElement('iframe');   
  32.             comet.connection.setAttribute('id',     'comet_iframe');   
  33.             comet.connection.setAttribute('src',    server);   
  34.             with (comet.connection.style) {   
  35.                 position   = "absolute";   
  36.                 left       = top   = "-100px";   
  37.                 height     = width = "1px";   
  38.                 visibility = "hidden";   
  39.             }   
  40.             document.body.appendChild(comet.connection);   
  41.   
  42.         } else {   
  43.             comet.connection = document.createElement('iframe');   
  44.             comet.connection.setAttribute('id',     'comet_iframe');   
  45.             with (comet.connection.style) {   
  46.                 left       = top   = "-100px";   
  47.                 height     = width = "1px";   
  48.                 visibility = "hidden";   
  49.                 display    = 'none';   
  50.             }   
  51.             comet.iframediv = document.createElement('iframe');   
  52.             comet.iframediv.setAttribute('src', server);   
  53.             comet.connection.appendChild(comet.iframediv);   
  54.             document.body.appendChild(comet.connection);   
  55.         }   
  56.     },   
  57.   
  58.     //添加用户   
  59.     newUser:function(data){   
  60.         var list = document.getElementById('userList');   
  61.         var li = document.createElement('li');   
  62.         li.setAttribute("id","u1"+data);   
  63.         li.innerHTML = data;   
  64.         list.appendChild(li);   
  65.   
  66.         var user = document.getElementById('user');   
  67.         var option = document.createElement('option');   
  68.         option.setAttribute("id","u2"+data);   
  69.         option.innerHTML = data;   
  70.         user.appendChild(option);   
  71.     },   
  72.   
  73.     //删除用户   
  74.     deleteUser:function(data){   
  75.         $('#u1'+data).remove();   
  76.         $('#u2'+data).remove();   
  77.     },   
  78.   
  79.     //添加公共消息   
  80.     newMessage:function(data){   
  81.         var list = document.getElementById('messageList');   
  82.         var li = document.createElement('li');   
  83.         li.innerHTML = data;   
  84.   
  85.         list.appendChild(li);   
  86.     },   
  87.   
  88.     //添加私人消息   
  89.     privateMessage:function(data){   
  90.         var list = document.getElementById('privateMessage');   
  91.         var li = document.createElement('li');   
  92.         li.innerHTML = data;   
  93.   
  94.         list.appendChild(li);   
  95.     },   
  96.   
  97.     //退出   
  98.     onUnload: function() {   
  99.         if (comet.connection) {   
  100.             comet.connection = false;   
  101.         }   
  102.     }   
  103. }//comet end   
  104.                
  105. if (window.addEventListener) {   
  106.     window.addEventListener("load", comet.initialize, false);   
  107.     window.addEventListener("unload", comet.onUnload, false);   
  108. else if (window.attachEvent) {   
  109.     window.attachEvent("onload", comet.initialize);   
  110.     window.attachEvent("onunload", comet.onUnload);   
  111. }   
  112. </script>   
  113. </head>   
  114. <body>   
  115. <script type="text/javascript">   
  116. function sendAll(){   
  117.     var list = document.getElementById('privateMessage');   
  118.     var li = document.createElement('li');   
  119.     li.innerHTML = "I said to "+$("#user").val()+": " + $("#message").val();   
  120.     list.appendChild(li);   
  121.        
  122.      $.ajax({   
  123.          type: "POST",   
  124.          url: "MessageServlet",    
  125.          data: "message="+$("#message").val()+"&user="+$("#user").val()+"&from=<%=request.getParameter("name")%>"  
  126.      });   
  127. }   
  128. </script>   
  129. <div class="container_12">   
  130. <div class="grid_10">   
  131.     <div>公共聊天</div>   
  132.     <div id="messageList" style="height:250px;overflow:scroll;border:solid 1px black;">   
  133.        
  134.     </div>   
  135.     <br/>   
  136.     <div>个人聊天</div>   
  137.     <div id="privateMessage" style="height:150px;overflow:scroll;border:solid 1px black;">   
  138.        
  139.     </div>   
  140.     <br/>   
  141.     <div>   
  142.         <select id="user" style="width:100px;overflow:scroll;">   
  143.             <option value="all">All</option>   
  144.         </select>   
  145.         <input type="text" id="message" size="40"></input>   
  146.         <input type="button" value="发言" onclick="sendAll()">   
  147.     </div>   
  148. </div>   
  149. <div class="grid_2">   
  150.     <h3>用户列表</h3>   
  151.     <ol id="userList">   
  152.        
  153.     </ol>   
  154. </div>   
  155. </div>   
  156. </body>   
  157. </html>  
     <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="jquery-1.4.2.min.js"></script>
<link rel="stylesheet" href="960.css" />
<title>Comet Chat Demo</title>
<script type="text/javascript">
var server = 'http://localhost:8080/CometDemo/ChatComet?name=<%=request.getParameter("name")%>';

var comet = {
	connection   : false,
	iframediv    : false,

	initialize: function() {
		if (navigator.appVersion.indexOf("MSIE") != -1) {
			comet.connection = new ActiveXObject("htmlfile");
			comet.connection.open();
			comet.connection.write("<html>");
			comet.connection.write("<script>document.domain = '"+document.domain+"'");
			comet.connection.write("</html>");
			comet.connection.close();
			comet.iframediv = comet.connection.createElement("div");
			comet.connection.appendChild(comet.iframediv);
			comet.connection.parentWindow.comet = comet;
			comet.iframediv.innerHTML = "<iframe id='comet_iframe' src='"+server+"'></iframe>";

		} else if (navigator.appVersion.indexOf("KHTML") != -1) {
			comet.connection = document.createElement('iframe');
			comet.connection.setAttribute('id',     'comet_iframe');
			comet.connection.setAttribute('src',    server);
			with (comet.connection.style) {
				position   = "absolute";
				left       = top   = "-100px";
				height     = width = "1px";
				visibility = "hidden";
			}
		    document.body.appendChild(comet.connection);

		} else {
			comet.connection = document.createElement('iframe');
			comet.connection.setAttribute('id',     'comet_iframe');
			with (comet.connection.style) {
			    left       = top   = "-100px";
			    height     = width = "1px";
			    visibility = "hidden";
			    display    = 'none';
			}
			comet.iframediv = document.createElement('iframe');
			comet.iframediv.setAttribute('src', server);
			comet.connection.appendChild(comet.iframediv);
			document.body.appendChild(comet.connection);
		}
	},

	//添加用户
	newUser:function(data){
		var list = document.getElementById('userList');
		var li = document.createElement('li');
		li.setAttribute("id","u1"+data);
		li.innerHTML = data;
		list.appendChild(li);

		var user = document.getElementById('user');
		var option = document.createElement('option');
		option.setAttribute("id","u2"+data);
		option.innerHTML = data;
		user.appendChild(option);
	},

	//删除用户
	deleteUser:function(data){
		$('#u1'+data).remove();
		$('#u2'+data).remove();
	},

	//添加公共消息
	newMessage:function(data){
		var list = document.getElementById('messageList');
		var li = document.createElement('li');
		li.innerHTML = data;

		list.appendChild(li);
	},

	//添加私人消息
	privateMessage:function(data){
		var list = document.getElementById('privateMessage');
		var li = document.createElement('li');
		li.innerHTML = data;

		list.appendChild(li);
	},

	//退出
	onUnload: function() {
		if (comet.connection) {
			comet.connection = false;
		}
	}
}//comet end
			
if (window.addEventListener) {
	window.addEventListener("load", comet.initialize, false);
	window.addEventListener("unload", comet.onUnload, false);
} else if (window.attachEvent) {
	window.attachEvent("onload", comet.initialize);
	window.attachEvent("onunload", comet.onUnload);
}
</script>
</head>
<body>
<script type="text/javascript">
function sendAll(){
	var list = document.getElementById('privateMessage');
	var li = document.createElement('li');
	li.innerHTML = "I said to "+$("#user").val()+": " + $("#message").val();
	list.appendChild(li);
	
	 $.ajax({
		 type: "POST",
		 url: "MessageServlet", 
		 data: "message="+$("#message").val()+"&user="+$("#user").val()+"&from=<%=request.getParameter("name")%>"
	 });
}
</script>
<div class="container_12">
<div class="grid_10">
	<div>公共聊天</div>
	<div id="messageList" style="height:250px;overflow:scroll;border:solid 1px black;">
	
	</div>
	<br/>
	<div>个人聊天</div>
	<div id="privateMessage" style="height:150px;overflow:scroll;border:solid 1px black;">
	
	</div>
	<br/>
	<div>
		<select id="user" style="width:100px;overflow:scroll;">
			<option value="all">All</option>
		</select>
		<input type="text" id="message" size="40"></input>
		<input type="button" value="发言" onclick="sendAll()">
	</div>
</div>
<div class="grid_2">
	<h3>用户列表</h3>
	<ol id="userList">
	
	</ol>
</div>
</div>
</body>
</html>


ChatServlet.java
Java代码 复制代码
  1. package demo;   
  2.   
  3. import java.io.IOException;   
  4. import java.io.InputStream;   
  5. import java.io.PrintWriter;   
  6. import java.util.HashMap;   
  7. import java.util.Map;   
  8. import java.util.Map.Entry;   
  9.   
  10. import javax.servlet.ServletException;   
  11. import javax.servlet.http.HttpServlet;   
  12. import javax.servlet.http.HttpServletRequest;   
  13. import javax.servlet.http.HttpServletResponse;   
  14.   
  15. import org.apache.catalina.CometEvent;   
  16. import org.apache.catalina.CometProcessor;   
  17.   
  18. /**  
  19.  *   
  20.  * @author Aries Zhao  
  21.  *   
  22.  */  
  23. public class ChatServlet extends HttpServlet implements CometProcessor {   
  24.   
  25.     private static final long serialVersionUID = -3667180332947986301L;   
  26.   
  27.     // <用户,长连接>   
  28.     protected static Map<String, HttpServletResponse> connections = new HashMap<String, HttpServletResponse>();   
  29.   
  30.     // 消息推送线程   
  31.     protected static MessageSender messageSender = null;   
  32.   
  33.     public void init() throws ServletException {   
  34.         // 启动消息推送线程   
  35.         messageSender = new MessageSender();   
  36.         Thread messageSenderThread = new Thread(messageSender, "MessageSender["  
  37.                 + getServletContext().getContextPath() + "]");   
  38.         messageSenderThread.setDaemon(true);   
  39.         messageSenderThread.start();   
  40.     }   
  41.   
  42.     public void destroy() {   
  43.         connections.clear();   
  44.         messageSender.stop();   
  45.         messageSender = null;   
  46.     }   
  47.   
  48.     public void event(CometEvent event) throws IOException, ServletException {   
  49.         HttpServletRequest request = event.getHttpServletRequest();   
  50.         HttpServletResponse response = event.getHttpServletResponse();   
  51.   
  52.         // 昵称   
  53.         String name = request.getParameter("name");   
  54.         if (name == null) {   
  55.             return;   
  56.         }   
  57.   
  58.         if (event.getEventType() == CometEvent.EventType.BEGIN) {   
  59.             // Http连接空闲超时   
  60.             event.setTimeout(Integer.MAX_VALUE);   
  61.             log("Begin for session: " + request.getSession(true).getId());   
  62.   
  63.             // 创建Comet Iframe   
  64.             PrintWriter writer = response.getWriter();   
  65.             writer   
  66.                     .println("<!doctype html public \"-//w3c//dtd html 4.0 transitional//en\">");   
  67.             writer   
  68.                     .println("<html><head><script type=\"text/javascript\">var comet = window.parent.comet;</script></head><body>");   
  69.             writer.println("<script type=\"text/javascript\">");   
  70.             writer.println("var comet = window.parent.comet;");   
  71.             writer.println("</script>");   
  72.             writer.flush();   
  73.   
  74.             // for chrome   
  75.             if (request.getHeader("User-Agent").contains("KHTML")) {   
  76.                 for (int i = 0; i < 100; i++) {   
  77.                     writer.print("<input type=hidden name=none value=none>");   
  78.                 }   
  79.                 writer.flush();   
  80.             }   
  81.   
  82.             // 欢迎信息   
  83.             writer.print("<script type=\"text/javascript\">");   
  84.             writer.println("comet.newMessage('Hello " + name + ", Welcome!');");   
  85.             writer.print("</script>");   
  86.             writer.flush();   
  87.   
  88.             // 通知其他用户有新用户登陆   
  89.             if (!connections.containsKey(name)) {   
  90.                 messageSender.login(name);   
  91.             }   
  92.   
  93.             // 推送已经登陆的用户信息   
  94.             for (String user : connections.keySet()) {   
  95.                 if (!user.equals(name)) {   
  96.                     writer.print("<script type=\"text/javascript\">");   
  97.                     writer.println("comet.newUser('" + user + "');");   
  98.                     writer.print("</script>");   
  99.                 }   
  100.             }   
  101.             writer.flush();   
  102.   
  103.             synchronized (connections) {   
  104.                 connections.put(name, response);   
  105.             }   
  106.         } else if (event.getEventType() == CometEvent.EventType.ERROR) {   
  107.             log("Error for session: " + request.getSession(true).getId());   
  108.             synchronized (connections) {   
  109.                 connections.remove(name);   
  110.             }   
  111.             event.close();   
  112.         } else if (event.getEventType() == CometEvent.EventType.END) {   
  113.             log("End for session: " + request.getSession(true).getId());   
  114.             messageSender.logout(name);   
  115.             synchronized (connections) {   
  116.                 connections.remove(name);   
  117.             }   
  118.             PrintWriter writer = response.getWriter();   
  119.             writer.println("</body></html>");   
  120.             event.close();   
  121.         } else if (event.getEventType() == CometEvent.EventType.READ) {   
  122.             InputStream is = request.getInputStream();   
  123.             byte[] buf = new byte[512];   
  124.             do {   
  125.                 int n = is.read(buf); // can throw an IOException   
  126.                 if (n > 0) {   
  127.                     log("Read " + n + " bytes: " + new String(buf, 0, n)   
  128.                             + " for session: "  
  129.                             + request.getSession(true).getId());   
  130.                 } else if (n < 0) {   
  131.                     return;   
  132.                 }   
  133.             } while (is.available() > 0);   
  134.         }   
  135.     }   
  136.   
  137.     // 发送消息给所有人   
  138.     public static void send(String message) {   
  139.         messageSender.send("*", message);   
  140.     }   
  141.   
  142.     // 向某个连接发送消息   
  143.     public static void send(String name, String message) {   
  144.         messageSender.send(name, message);   
  145.     }   
  146.   
  147.     public class MessageSender implements Runnable {   
  148.   
  149.         protected boolean running = true;   
  150.         protected Map<String, String> messages = new HashMap<String, String>();   
  151.   
  152.         public MessageSender() {   
  153.   
  154.         }   
  155.   
  156.         public void stop() {   
  157.             running = false;   
  158.         }   
  159.   
  160.         // 新用户登陆   
  161.         public void login(String name) {   
  162.             synchronized (messages) {   
  163.                 messages.put("Login", name);   
  164.                 messages.notify();   
  165.             }   
  166.         }   
  167.   
  168.         // 用户下线   
  169.         public void logout(String name) {   
  170.             synchronized (messages) {   
  171.                 messages.put("Logout", name);   
  172.                 messages.notify();   
  173.             }   
  174.         }   
  175.   
  176.         // 发送消息   
  177.         public void send(String user, String message) {   
  178.             synchronized (messages) {   
  179.                 messages.put(user, message);   
  180.                 messages.notify();   
  181.             }   
  182.         }   
  183.   
  184.         public void run() {   
  185.             while (running) {   
  186.                 if (messages.size() == 0) {   
  187.                     try {   
  188.                         synchronized (messages) {   
  189.                             messages.wait();   
  190.                         }   
  191.                     } catch (InterruptedException e) {   
  192.                         // Ignore   
  193.                     }   
  194.                 }   
  195.   
  196.                 synchronized (connections) {   
  197.                     synchronized (messages) {   
  198.                         // 推送消息队列中的消息   
  199.                         for (Entry<String, String> message : messages   
  200.                                 .entrySet()) {   
  201.                             if (message.getKey().equals("Login")) {// 新用户登陆   
  202.                                 log(message.getValue() + " Login");   
  203.                                 for (HttpServletResponse response : connections   
  204.                                         .values()) {   
  205.                                     try {   
  206.                                         PrintWriter writer = response   
  207.                                                 .getWriter();   
  208.                                         writer   
  209.                                                 .print("<script type=\"text/javascript\">");   
  210.                                         writer   
  211.                                                 .println("comet.newMessage('Welcome "  
  212.                                                         + message.getValue()   
  213.                                                         + " !');");   
  214.                                         writer.println("comet.newUser('"  
  215.                                                 + message.getValue() + "');");   
  216.                                         writer.print("</script>");   
  217.                                         writer.flush();   
  218.                                     } catch (IOException e) {   
  219.                                         log("IOExeption execute command", e);   
  220.                                     }   
  221.                                 }   
  222.                             } else if ("Logout".equals(message.getKey())) {// 用户退出   
  223.                                 log(message.getValue() + " Logout");   
  224.                                 for (HttpServletResponse response : connections   
  225.                                         .values()) {   
  226.                                     try {   
  227.                                         PrintWriter writer = response   
  228.                                                 .getWriter();   
  229.                                         writer   
  230.                                                 .print("<script type=\"text/javascript\">");   
  231.                                         writer.println("comet.newMessage('88, "  
  232.                                                 + message.getValue() + "');");   
  233.                                         writer.println("comet.deleteUser('"  
  234.                                                 + message.getValue() + "');");   
  235.                                         writer.print("</script>");   
  236.                                         writer.flush();   
  237.                                     } catch (IOException e) {   
  238.                                         log("IOExeption execute command", e);   
  239.                                     }   
  240.                                 }   
  241.                             } else if ("*".equals(message.getKey())) {// 群发消息   
  242.                                 log("Send message: " + message.getValue()   
  243.                                         + " to everyone.");   
  244.                                 for (HttpServletResponse response : connections   
  245.                                         .values()) {   
  246.                                     try {   
  247.                                         PrintWriter writer = response   
  248.                                                 .getWriter();   
  249.                                         writer   
  250.                                                 .print("<script type=\"text/javascript\">");   
  251.                                         writer.println("comet.newMessage('"  
  252.                                                 + message.getValue() + "');");   
  253.                                         writer.print("</script>");   
  254.                                         writer.flush();   
  255.                                     } catch (IOException e) {   
  256.                                         log("IOExeption execute command", e);   
  257.                                     }   
  258.                                 }   
  259.                             } else {// 向某人发信息   
  260.                                 try {   
  261.                                     HttpServletResponse response = connections   
  262.                                             .get(message.getKey());   
  263.                                     PrintWriter writer = response.getWriter();   
  264.                                     writer   
  265.                                             .print("<script type=\"text/javascript\">");   
  266.                                     writer.println("comet.privateMessage('"  
  267.                                             + message.getValue() + "');");   
  268.                                     writer.print("</script>");   
  269.                                     writer.flush();   
  270.                                 } catch (IOException e) {   
  271.                                     log("IOExeption sending message", e);   
  272.                                 }   
  273.                             }   
  274.                             // 从消息队列中删除消息   
  275.                             messages.remove(message.getKey());   
  276.                         }   
  277.                     }   
  278.                 }   
  279.             }   
  280.         }   
  281.     }   
  282. }  
package demo;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.CometEvent;
import org.apache.catalina.CometProcessor;

/**
 * 
 * @author Aries Zhao
 * 
 */
public class ChatServlet extends HttpServlet implements CometProcessor {

	private static final long serialVersionUID = -3667180332947986301L;

	// <用户,长连接>
	protected static Map<String, HttpServletResponse> connections = new HashMap<String, HttpServletResponse>();

	// 消息推送线程
	protected static MessageSender messageSender = null;

	public void init() throws ServletException {
		// 启动消息推送线程
		messageSender = new MessageSender();
		Thread messageSenderThread = new Thread(messageSender, "MessageSender["
				+ getServletContext().getContextPath() + "]");
		messageSenderThread.setDaemon(true);
		messageSenderThread.start();
	}

	public void destroy() {
		connections.clear();
		messageSender.stop();
		messageSender = null;
	}

	public void event(CometEvent event) throws IOException, ServletException {
		HttpServletRequest request = event.getHttpServletRequest();
		HttpServletResponse response = event.getHttpServletResponse();

		// 昵称
		String name = request.getParameter("name");
		if (name == null) {
			return;
		}

		if (event.getEventType() == CometEvent.EventType.BEGIN) {
			// Http连接空闲超时
			event.setTimeout(Integer.MAX_VALUE);
			log("Begin for session: " + request.getSession(true).getId());

			// 创建Comet Iframe
			PrintWriter writer = response.getWriter();
			writer
					.println("<!doctype html public \"-//w3c//dtd html 4.0 transitional//en\">");
			writer
					.println("<html><head><script type=\"text/javascript\">var comet = window.parent.comet;</script></head><body>");
			writer.println("<script type=\"text/javascript\">");
			writer.println("var comet = window.parent.comet;");
			writer.println("</script>");
			writer.flush();

			// for chrome
			if (request.getHeader("User-Agent").contains("KHTML")) {
				for (int i = 0; i < 100; i++) {
					writer.print("<input type=hidden name=none value=none>");
				}
				writer.flush();
			}

			// 欢迎信息
			writer.print("<script type=\"text/javascript\">");
			writer.println("comet.newMessage('Hello " + name + ", Welcome!');");
			writer.print("</script>");
			writer.flush();

			// 通知其他用户有新用户登陆
			if (!connections.containsKey(name)) {
				messageSender.login(name);
			}

			// 推送已经登陆的用户信息
			for (String user : connections.keySet()) {
				if (!user.equals(name)) {
					writer.print("<script type=\"text/javascript\">");
					writer.println("comet.newUser('" + user + "');");
					writer.print("</script>");
				}
			}
			writer.flush();

			synchronized (connections) {
				connections.put(name, response);
			}
		} else if (event.getEventType() == CometEvent.EventType.ERROR) {
			log("Error for session: " + request.getSession(true).getId());
			synchronized (connections) {
				connections.remove(name);
			}
			event.close();
		} else if (event.getEventType() == CometEvent.EventType.END) {
			log("End for session: " + request.getSession(true).getId());
			messageSender.logout(name);
			synchronized (connections) {
				connections.remove(name);
			}
			PrintWriter writer = response.getWriter();
			writer.println("</body></html>");
			event.close();
		} else if (event.getEventType() == CometEvent.EventType.READ) {
			InputStream is = request.getInputStream();
			byte[] buf = new byte[512];
			do {
				int n = is.read(buf); // can throw an IOException
				if (n > 0) {
					log("Read " + n + " bytes: " + new String(buf, 0, n)
							+ " for session: "
							+ request.getSession(true).getId());
				} else if (n < 0) {
					return;
				}
			} while (is.available() > 0);
		}
	}

	// 发送消息给所有人
	public static void send(String message) {
		messageSender.send("*", message);
	}

	// 向某个连接发送消息
	public static void send(String name, String message) {
		messageSender.send(name, message);
	}

	public class MessageSender implements Runnable {

		protected boolean running = true;
		protected Map<String, String> messages = new HashMap<String, String>();

		public MessageSender() {

		}

		public void stop() {
			running = false;
		}

		// 新用户登陆
		public void login(String name) {
			synchronized (messages) {
				messages.put("Login", name);
				messages.notify();
			}
		}

		// 用户下线
		public void logout(String name) {
			synchronized (messages) {
				messages.put("Logout", name);
				messages.notify();
			}
		}

		// 发送消息
		public void send(String user, String message) {
			synchronized (messages) {
				messages.put(user, message);
				messages.notify();
			}
		}

		public void run() {
			while (running) {
				if (messages.size() == 0) {
					try {
						synchronized (messages) {
							messages.wait();
						}
					} catch (InterruptedException e) {
						// Ignore
					}
				}

				synchronized (connections) {
					synchronized (messages) {
						// 推送消息队列中的消息
						for (Entry<String, String> message : messages
								.entrySet()) {
							if (message.getKey().equals("Login")) {// 新用户登陆
								log(message.getValue() + " Login");
								for (HttpServletResponse response : connections
										.values()) {
									try {
										PrintWriter writer = response
												.getWriter();
										writer
												.print("<script type=\"text/javascript\">");
										writer
												.println("comet.newMessage('Welcome "
														+ message.getValue()
														+ " !');");
										writer.println("comet.newUser('"
												+ message.getValue() + "');");
										writer.print("</script>");
										writer.flush();
									} catch (IOException e) {
										log("IOExeption execute command", e);
									}
								}
							} else if ("Logout".equals(message.getKey())) {// 用户退出
								log(message.getValue() + " Logout");
								for (HttpServletResponse response : connections
										.values()) {
									try {
										PrintWriter writer = response
												.getWriter();
										writer
转载自:http://a
分享到:
评论

相关推荐

    多种方式模拟服务器推送客户端

    在Web开发中,服务器向客户端实时推送数据是常见...在名为"serverPush"的压缩包文件中,可能包含了实现上述各种服务器推送方式的JAVA代码示例,开发者可以通过阅读和学习这些代码,进一步理解并掌握服务器推送的技术。

    web推送 comet技术

    Comet技术是一种基于HTTP长连接的Web实时通信技术,它允许服务器向客户端主动推送数据,而无需客户端发起新的请求。这种技术打破了传统的HTTP请求-响应模型,极大地提升了Web应用的实时性和交互性,尤其适用于股票...

    asp.net comet例子

    ASP.NET Comet是一个技术概念,它涉及到了Web应用程序中的实时通信,特别是服务器向客户端推送数据的能力。在传统的HTTP协议中,服务器通常在客户端发起请求时才响应,而在Comet模式下,服务器可以保持一个连接开放...

    PushMessage JavaWeb聊天 推送 实现

    3. **Comet技术**:Comet是长轮询的一种抽象,它包括了多种实现方式,如流、隐藏IFrame和JSONP等,目的是实现服务器到浏览器的推送。 4. **Servlet与WebSocket结合**:在JavaWeb应用中,CharServletPush可能表示一...

    comet demo

    "消息推送"是Comet的核心特性,服务器能够主动将新的消息推送给客户端,无需客户端频繁地轮询请求,从而提高了效率并降低了服务器压力。 Comet技术通常有几种实现方式,包括长轮询(Long Polling)、iframe、流...

    asp.net 消息推送

    ASP.NET 消息推送技术是Web开发中的一个重要概念,它允许服务器主动向客户端发送数据,而无需客户端(如浏览器)不断地发起请求。这种技术在实时性要求高的应用场景中非常关键,比如聊天应用、股票更新、在线游戏等...

    pushlet 和comet 资料介绍

    Pushlet和Comet技术是Web服务器向浏览器推送数据的两种策略,主要用于实现实时的、双向的通信。这两种技术在传统的HTTP协议基础上进行了扩展,克服了HTTP请求-响应模型的限制,使得服务器能够主动向客户端推送数据,...

    论文研究-一个基于push技术的web实时网络管理框架 .pdf

    服务器可以不断地向这个隐藏的IFrame推送数据,而JavaScript则可以处理这些数据并更新主页面。这种方式可以持续不断地更新信息,而不会被浏览器关闭或网络异常打断。 知识点五:TMN管理模型与实时网络管理框架的...

    使用nodejs搭建最简单的comet原型参考.pdf

    Comet是一种基于HTTP长连接的服务器推送技术,旨在提供实时的Web应用程序交互。它与AJAX类似,但不同之处在于,AJAX通常依赖于短连接和异步请求,而Comet则保持一个开放的HTTP连接,允许服务器主动向客户端推送数据...

    网易邮箱的Comet实践_陈志凌(网易)

    网易邮箱使用Comet技术来实现其Webim(邮箱聊天)和Pushmail(邮件推送)等项目。这些项目需要实时更新和即时推送信息给用户,因此选择Comet作为技术支持。 5. 如何选择适合的方案: 当选择适合的Comet实现方案时...

    dwr反推demo

    DWR2.x版本引入了反推(Reverse Ajax)技术,也被称为服务器端推送(Server-Side Push),它打破了传统Ajax模式中由客户端发起请求、服务器响应的单向通信模式,实现了服务器端可以主动将数据推送到客户端的功能。...

    AJAX项目开发指南

    - **使用Server Push技术**:例如Comet技术,可以让服务器主动推送数据到客户端。 - **选择合适的框架**:根据项目需求选择合适的框架,如DWR、Dojo Toolkit等。 ##### 3.2 实现案例 - **即时股市报价**:可以采用...

    SD大会精品讲座:利用AJAX/Java 技术建立高流量的即时双向沟通网站

    - **Comet**:一种实现Server Push的技术,通过对HTTP连接的长期保持来实现服务器向客户端推送数据。 - **WebSocket**:提供了全双工的通信通道,可以实现客户端和服务器之间的双向通信。 #### 六、应用实例 - ...

    PHP使用反向Ajax技术实现在线客服系统详解

    反向Ajax技术,又称为服务器推技术(server push),是一种允许服务器主动向客户端发送数据的技术。与传统Ajax技术的客户端拉数据(客户端通过定时向服务器发送请求来获取最新数据)不同,反向Ajax技术中,服务器能够...

Global site tag (gtag.js) - Google Analytics