- 浏览: 14092 次
最新评论
Comet基于iframe的服务器推送(Server Push)例子
- 博客分类:
- 技术杂绘
Comet基于iframe的服务器推送(Server Push)例子
2011年02月07日
服务器推送技术(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聊天室: 仅仅是一个Demo,可以从index.jsp?name=yourNickName进入,实现了上线,下线通知,群发,消息功能,性能还没有测试...
目前能够正常在IE,FireFox和Chrome下正常运行,但在Chrome下会一直加载不完,不知道有没有办法解决?还有不知道能不能在此基础之上搞一个基于iframe的Comet工具,包括前台js和后台java.
首先修改Tomcat配置文件
修改server.xml中,底层用NIO实现的Http连接器
index.jsp Comet Chat Demo '; 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(""); comet.connection.write("document.domain = '"+document.domain+"'"); comet.connection.write(""); comet.connection.close(); comet.iframediv = comet.connection.createElement("div"); comet.connection.appendChild(comet.iframediv); comet.connection.parentWindow.comet = comet; comet.iframediv.innerHTML = ""; } 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); } // --> " }); } // --> 公共聊天 个人聊天 All 用户列表 ChatServlet.java 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 connections = new HashMap(); // 消息推送线程 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(""); writer .println(""); writer.println(""); writer.flush(); // for chrome if (request.getHeader("User-Agent").contains("KHTML") ) { for (int i = 0; i "); } writer.flush(); } // 欢迎信息 writer.print(""); writer.flush(); // 通知其他用户有新用户登陆 if (!connections.containsKey(name)) { messageSender.login(name); } // 推送已经登陆的用户信息 for (String user : connections.keySet()) { if (!user.equals(name)) { writer.print(""); } } 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(""); 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); } } // 发送消息给所有人 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 messages = new HashMap(); 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 message : messages .entrySet()) { if (message.getKey().equals("Login")) {// 新用户登陆 log(message.getValue() + " Login"); for (HttpServletResponse response : connections .values()) { try { PrintWriter writer = response .getWriter(); writer .print(""); 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 .print(""); writer.flush(); } catch (IOException e) { log("IOExeption execute command", e); } } } else if ("*".equals(message.getKey())) {// 群发消息 log("Send message: " + message.getValue() + " to everyone."); for (HttpServletResponse response : connections .values()) { try { PrintWriter writer = response .getWriter(); writer .print(""); writer.flush(); } catch (IOException e) { log("IOExeption execute command", e); } } } else {// 向某人发信息 try { HttpServletResponse response = connections .get(message.getKey()); PrintWriter writer = response.getWriter(); writer .print(""); writer.flush(); } catch (IOException e) { log("IOExeption sending message", e); } } // 从消息队列中删除消息 messages.remove(message.getKey()); } } } } } } }
发表评论
-
AJAX 长轮询
2012-01-20 10:50 900AJAX 长轮询 2010年06月24 ... -
AJAX(XMLHttpRequest)进行跨域请求方法详解
2012-01-20 10:50 1147AJAX(XMLHttpRequest)进行跨 ... -
解决js跨域问题
2012-01-20 10:50 561解决js跨域问题 2011年03月14日 解决js跨域问 ... -
JS 报错 没有权限
2012-01-20 10:50 618JS 报错 没有权限 2010年12月13日 没有权限是 ... -
win7安vc2008编译报link : fatal error lnk1000: internal error during incrbuildimage_竹林英客
2012-01-19 15:49 554win7安vc2008编译报link : fatal erro ... -
LOG_ERROR::Permission denied (13) in chk_file_sec
2012-01-19 15:49 2069LOG_ERROR::Permission denied (1 ... -
mysql远程无法登陆出现ERROR 2003 (HY000)...解决方法
2012-01-19 15:49 786mysql远程无法登陆出现ERROR 2003 (HY000) ... -
LOL NSIS Error
2012-01-19 15:49 1276LOL NSIS Error 2011年06月06日 出 ... -
转:错误处理(Error-Handling):为何、何时、如何(rev#2)
2012-01-19 15:49 626转:错误处理(Error-Handling ... -
虚伪的友情再见!!!!
2012-01-17 05:31 578虚伪的友情再见!!!! 2011 ... -
好时光,是美人
2012-01-17 05:31 451好时光,是美人 2011年11月26日 ... -
第一言:曹操
2012-01-17 05:31 688第一言:曹操 2011年11月26日 文章出处:http ... -
武林秘籍――《骂人宝典》
2012-01-17 05:31 781武林秘籍――《骂人宝 ... -
变身-室友跳楼的诡异事件
2012-01-17 05:30 887变身-室友跳楼的诡异事 ... -
2011-12-22
2012-01-16 04:27 4322011-12-22 2011年12月22日 室内设计原 ... -
远古的孔加工工具(转)
2012-01-16 04:27 507远古的孔加工工具(转) ... -
孔子的政治思想
2012-01-16 04:26 623孔子的政治思想 2011年11月27日 孔子是中国政治思 ...
相关推荐
通过tomcat服务器,向网页发送即时消息。comet的小例子,可以直接运行,用tomcat6.0。
Comet 有时也称反向 Ajax 或服务器端推技术(server-side push)。其思想很简单:将数据直接从服务器推到浏览器,而不必等到浏览器请求数据。听起来简单,但是如果熟悉 Web 应用程序,尤其是 HTTP 协议,那么您就会...
java comet服务器推送使用步骤及例子
Comet服务器推送技术
它分为服务端与客户端两部分,你只要将服务器端(JAR文件,目前仅支持Tomcat6、7)放入WEB-INF\lib,客户端(JavaScript文件)引入到页面,那么你的应用就具备了向客户端推送信息的能力,而你仅需要在服务器端调用Comet4...
comet iframe phpcomet iframe phpcomet iframe phpcomet iframe phpcomet iframe phpcomet iframe php
Comet-服务器推送解决方案.docx
Java comet服务器推送(聊天)实现代码。
comet4j 自己写的消息推送 觉得实用
这个项目是基于tomcat,comet4j的技术来实现推送消息到web页面,可以直接导入,直接运行的,里面包含了项目所需要的comet4j-tomcat7.jar(tomcat7的就导入这个),comet4j.js(页面引入这个js),等jar包,对于想要学习...
NULL 博文链接:https://frank59.iteye.com/blog/1455050
PHP防Sina微薄无刷新服务器推送(comet)原理,防微薄无刷新
NULL 博文链接:https://justcoding.iteye.com/blog/1497445
基于服务器推送框架 Comet4J ,后台模拟实时生成 gps 坐标信息然后再推送到前端页面显示。 如果按照以前的常见方式,我们很可能想到的实现是采用 ajax 前端页面,每隔多长时间向服务器发起一次请求。这是客户端主动...
javaweb消息推送 基于comet实现局域网内部通讯(聊天室)demo 功能特性 推送消息广播。 推送定向消息。 提供连接上线前、上线、下线前、下线、发送消息等多种可处理事件。 消息缓存机制,确保长轮询工作模式下不丢失...
Comet:基于 HTTP 长连接的“服务器推”技术
dwr comet web push 服务器主动推送
Comet:基于_HTTP_长连接的“服务器推”技术 Comet:基于_HTTP_长连接的“服务器推”技术 Comet:基于_HTTP_长连接的“服务器推”技术 简介
NULL 博文链接:https://zzc1684.iteye.com/blog/2187874