浏览 19219 次
精华帖 (3) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (1)
|
|
---|---|
作者 | 正文 |
发表时间:2010-12-14
下面是在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> 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()); } } } } } } } 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-12-22
项目中用了amq的推 感觉还不错
|
|
返回顶楼 | |
发表时间:2011-01-21
用http://localhost:8080/CometDemo/index.jsp?name=comet1登录。
|
|
返回顶楼 | |
发表时间:2011-02-25
部署上去试了试,能运行。很好的demo!
|
|
返回顶楼 | |
发表时间:2011-02-26
我的为什么 不能正常运行
tomcat是6.0.26,也改了配置 还有什么需要注意的细节吗? |
|
返回顶楼 | |
发表时间:2011-02-26
感觉比较靠谱的方案客户端使用flash socket和服务端建立一个长连接。服务端可以用mina去实现,这样并发能力和处理能力很强的
|
|
返回顶楼 | |
发表时间:2011-02-26
melin 写道 感觉比较靠谱的方案客户端使用flash socket和服务端建立一个长连接。服务端可以用mina去实现,这样并发能力和处理能力很强的
就等html5 websocket, web dev们就解脱了 |
|
返回顶楼 | |
发表时间:2011-02-28
之前项目中的聊天室也想用这种方法,但无奈IE浏览器 ,尤其是老版本的浏览器不给力,只能换成了flex+socket
|
|
返回顶楼 | |
发表时间:2011-07-02
不错的例子,中文乱码,orz~~~
|
|
返回顶楼 | |