- 浏览: 5647 次
- 性别:
文章分类
最新评论
服务器推送技术(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连接器
index.jsp
- <%@ 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>
<%@ 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
- 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
- .print("<script type=\"text/javascript\">");
- writer.println("comet.newMessage('88, "
- + message.getValue() + "');");
- writer.println("comet.deleteUser('"
- + message.getValue() + "');");
- writer.print("</script>");
- 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("<script type=\"text/javascript\">");
- writer.println("comet.newMessage('"
- + message.getValue() + "');");
- writer.print("</script>");
- writer.flush();
- } catch (IOException e) {
- log("IOExeption execute command", e);
- }
- }
- } else {// 向某人发信息
- try {
- HttpServletResponse response = connections
- .get(message.getKey());
- PrintWriter writer = response.getWriter();
- writer
- .print("<script type=\"text/javascript\">");
- writer.println("comet.privateMessage('"
- + message.getValue() + "');");
- writer.print("</script>");
- writer.flush();
- } catch (IOException e) {
- log("IOExeption sending message", e);
- }
- }
- // 从消息队列中删除消息
- messages.remove(message.getKey());
- }
- }
- }
- }
- }
- }
- }
发表评论
-
xml 学习 总结
2012-04-23 11:12 647xml 是可扩展标记语言。 XSL 是指可扩展样式表语言 ( ... -
webservice基础知识
2012-03-22 11:24 782webservice 是异构平台之间的交互。不用语言之间的访问 ... -
oracle 中创建自增列的存储过程
2011-12-06 16:20 10691.存储过程如下: create or replace pr ... -
oracle创建命名空间和新用户
2011-12-06 11:50 1055Oracle安装完后,其中有一个缺省的数据库,除了这个缺省 ... -
守护线程和普通线程的区别
2011-09-20 14:34 12571.定义: 守护线程又称为“服务线程”。在没有用户线程可服 ...
相关推荐
通过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