WebSocket初建聊天室
来源:互联网 发布:社交网络评论音轨 编辑:程序博客网 时间:2024/05/14 04:35
最近在新观css3与html5相关的内容时,发现一个不错的好东西WebSocket,以前只是用过Oracle内建包的UTL_TCP,对于直接用socket与第三方服务进行通讯,确实是一件让人比较爽的事情,一些新思路顿时开阔起来。WebSocket允许浏览器里直接调用socket与服务器进行通讯,同时服务器还能主动给浏览器端进行消息推送,确实进一步丰富了BS结构,至少在浏览器里的游戏、新业务的实现,都提供了一个不错的技术选择,但是新技术毕竟还只是起步阶段,还有很多需要不断完善。
下面通过一个聊天室的例子,来慢慢了解WebSocket吧,详细的注释说明参考代码。
运行环境:
1 tomcat 8 用户web服务器及websocket服务器(其实是一个服务器,主要是WebSocket的TCP握手连接协议依赖于http协义,详细的文章参考http://tomcat.apache.org/tomcat-8.0-doc/web-socket-howto.html)
2 Myeclips 10.7,主要是用于类的编写(回头tomcat 8对应的webapps直接改到路径WebRoot对应的路径,即<Context path="/html5" docBase="D:\forDBCl\Html5\WebRoot" reloadable="true"></Context>),该版本的myeclips不支持集成tomcat 8
以上环境最大的不方便是没有办法进行调试。
强烈推荐:Myclips2015,上面可以直接开搞。
2 相关的脚本代码
2.1 WebSocket服务端参考代码,消息处理核心类
package com.cn.ljb.html5;import java.io.IOException;import java.util.Set;import java.util.concurrent.CopyOnWriteArraySet;import java.util.concurrent.atomic.AtomicInteger;import javax.websocket.OnClose;import javax.websocket.OnError;import javax.websocket.OnMessage;import javax.websocket.OnOpen;import javax.websocket.Session;import javax.websocket.server.ServerEndpoint;import com.cn.ljb.util.CommonUtils;//后面的字符串决定了请建立websocket连接地址内容的一部分@ServerEndpoint(value = "/websocket/chat")public class WSChatServlet{ private static final String GUEST_PREFIX = "Guest"; private static final AtomicInteger connectionIds = new AtomicInteger(0); private static final Set<WSChatServlet> connections = new CopyOnWriteArraySet<WSChatServlet>(); private Session lsession; private String connectFlag; private String nickname = "defaultNick"; public WSChatServlet() { connectFlag = GUEST_PREFIX + connectionIds.getAndIncrement(); System.out.println("-------WSChatServlet run construct function"+connectFlag); } @OnOpen public void start(Session session) { if(connections.contains(this)) System.out.println("session has exist in the Set,and Setsize="+connections.size()); else{ lsession = session; connections.add(this); } System.out.println("-----------onOpen CurrentConnections="+connections.size()+",Flag="+connectFlag); //String message = String.format("* %s %s", connectFlag, ".....加入聊天室......"); //broadcast(message); } @OnClose public void end() { if(connections.remove(this)){ System.out.println("-----------affter OnClose CurrentConnections="+connections.size()); broadcast("....我离开了聊天室...",this.nickname); } } @OnMessage public void incoming(String message) { // Never trust the clientString filteredMessage = CommonUtils.filter(message.toString());System.out.println("----sendMessage="+filteredMessage);String data[] = filteredMessage.split("[|]"); if(data!=null && data.length>0){ this.nickname = data[0]; broadcast(data[1],this.nickname); } } @OnError public void onError(Throwable t) throws Throwable { System.out.println("--------------Chat Error: " + t.toString()); } /** * @param type 1 连接消息 2 正式消息 3 离开消息 * @param msg 消息主体 * @param userName 消息发送人 */ private static void broadcast(String msg,String userName) { String jsonData = String.format("[{\"username\":\"%s\",\"content\":\"%s\"}]", userName+" "+CommonUtils.getLongDateNow(1),msg); for (WSChatServlet client : connections) { try { synchronized (client) { client.lsession.getBasicRemote().sendText(jsonData); } } catch (IOException e) { System.out.println("Chat Error: Failed to send message to client"); connections.remove(client); try { client.lsession.close(); } catch (IOException e1) { // Ignore } broadcast("......我离开了......",userName); } } } }
2.2 相关的工具辅助类,没有什么好讲的
package com.cn.ljb.util;import java.util.Calendar;import java.util.Date;public class CommonUtils { public static String filter(String message) { if (message == null) return (null); char content[] = new char[message.length()]; message.getChars(0, message.length(), content, 0); StringBuilder result = new StringBuilder(content.length + 50); for (int i = 0; i < content.length; i++) { switch (content[i]) { case '<': result.append("<"); break; case '>': result.append(">"); break; case '&': result.append("&"); break; case '"': result.append("""); break; default: result.append(content[i]); } } return (result.toString()); } public static String getLongDateNow(int dataType) {Calendar now = Calendar.getInstance();String dateString = null;now.setTime(new Date());switch(dataType){case 1:dateString = String.format("%04d-%02d-%02d %02d:%02d:%02d.%03d", now.get(Calendar.YEAR),now.get(Calendar.MONTH)+1,now.get(Calendar.DAY_OF_MONTH),now.get(Calendar.HOUR_OF_DAY),now.get(Calendar.MINUTE),now.get(Calendar.SECOND),now.get(Calendar.MILLISECOND));break;case 2:dateString = String.format("%04d-%02d-%02d", now.get(Calendar.YEAR),now.get(Calendar.MONTH)+1,now.get(Calendar.DAY_OF_MONTH));break;case 3:now.add(Calendar.DAY_OF_MONTH, -1);dateString = String.format("%04d-%02d-%02d", now.get(Calendar.YEAR),now.get(Calendar.MONTH)+1,now.get(Calendar.DAY_OF_MONTH));break;default:break;}return dateString;}}
3 前端页面代码及js代码(合到一起了)
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head><title>测试聊天程序基于WebSocket</title><style type="text/css">#console {border-radius:5px; border: 1px solid #CCCCCC; border-right-color: #999999; border-bottom-color: #999999; height: 300px; overflow-y: scroll; padding: 5px; width: 100%;}#console p {padding: 0;margin: 0;}</style></head><body><div id="mainContent" style="margin:0 auto;height:300px;width:50%;text-align:left;"><div id="console-container" style="margin:0 auto;height:300px;width:100%;padding-bottom:10px;"><div id="console"></div></div><p><nav><input type="button" value="加入群聊" onclick="joinChat()"></nav></p><p><span>昵称:</span><input id="nickname" type="text" style="width:20%;" placeholder="输入昵称"><input type="text" style="width:80%;" placeholder="输入你的聊天内容,回车发送" id="chat" /> <input type="button" value="发送消息" onclick="sendMessage()"></p></div></body></html><script type="text/javascript">var ynickname=null;var Chat = {};Chat.socket = null;Chat.connect = (function(host) { if ('WebSocket' in window) { Chat.socket = new WebSocket(host); } else if ('MozWebSocket' in window) { Chat.socket = new MozWebSocket(host); } else { Console.log("<h2 style='color: #ff0000'>该浏览器不支持websocket技术,请使用chrome或firefox等其他浏览器!</h2>"); return; } Chat.socket.onopen = function () { document.getElementById('chat').onkeydown = function(event) { if (event.keyCode == 13) { sendMessage(); } }; Chat.socket.send(ynickname+"|我加入了聊天哦"); //Console.log("消息:"+document.getElementById("nickname").value+" connect server success"); }; Chat.socket.onclose = function () { document.getElementById('chat').onkeydown = null; //Console.log("消息:"+document.getElementById("nickname").value+" close connection from server"); }; Chat.socket.onmessage = function (message) { Console.log(message.data); };});Chat.initialize = function() {if(ynickname==null){var nkname = document.getElementById('nickname').value; if(nkname==''){ alert("请先给自己取一个昵称,然后开始聊天呗!"); return; } else { ynickname = nkname; }} else {document.getElementById('nickname').value = ynickname;} if(Chat.socket==null) if (window.location.protocol == 'http:') { Chat.connect('ws://'+window.location.host+'/html5<strong>/websocket/chat</strong>'); } else { Chat.connect('wss://'+window.location.host+'/html5<strong>/websocket/chat</strong>'); } };Chat.sendConnMessage = (function(inputMsg) {if(inputMsg!='' || inputMsg!=null){var sendResult = Chat.socket.send(inputMsg);}});Chat.disConnect = (function() { Chat.socket.onclose();});var Console = {};Console.log = (function(message) {var jsonData = eval(message);if(jsonData.length>0){ var console = document.getElementById('console'); var p = document.createElement('p'); p.style.wordWrap = 'break-word'; p.innerHTML = "<font color='blue'>"+jsonData[0].username+":</font><br> "+jsonData[0].content; console.appendChild(p); while (console.childNodes.length > 25) { console.removeChild(console.firstChild); } console.scrollTop = console.scrollHeight; }});function joinChat(){Chat.initialize();}function sendMessage(){if(ynickname==null){var nkname = document.getElementById('nickname').value; if(nkname==''){ alert("请先给自己取一个昵称,然后开始聊天呗!"); return; } else { ynickname = nkname; }} else {document.getElementById('nickname').value = ynickname;}var message = document.getElementById('chat').value; if (message != '') { Chat.sendConnMessage(ynickname+"|"+message); document.getElementById('chat').value = ''; }}function leaveChat(){Chat.disConnect();}</script>
最终的基本代码是全部在上面了!我们再来看一个效果截图,拿个拔号路由器配置一条转发,就能轻松跟好友们搭建临时聊天室了。
- WebSocket初建聊天室
- WebSocket 聊天室
- WebSocket聊天室
- websocket聊天室
- websocket聊天室
- websocket聊天室
- html5 websocket聊天室 客户端
- C# WebSocket 聊天室
- Websocket学习--简易聊天室
- WebSocket+Netty实现聊天室
- WebSocket实现网页聊天室
- WebSocket实现即时聊天室
- Java webSocket 网页聊天室
- WebSocket + html 实现聊天室
- WebSocket入门聊天室
- websocket 聊天室(及时通讯)
- php websocket聊天室
- django channels websocket 聊天室
- ListView(二)通用的Adapter
- Android roboguice 开源框架使用
- 鼠标画矩形
- 删除第m个数字
- 对总线的一些认识
- WebSocket初建聊天室
- 《四》保存用户在apk中的设置为xml文件及回显用户设置
- HTML+CSS span height
- 对8086的总线的一些认识
- JS函数集合大全
- 创建任意大小数组
- Android ListView异步加载图片乱序问题,原因分析及解决方案
- 2013年山东省第四届ACM大学生程序设计竞赛——Mountain Subsequences
- MINI2440 console 初始化