WebSocket 实现群聊 - 简单测试例子
Posted simplejokerking
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WebSocket 实现群聊 - 简单测试例子相关的知识,希望对你有一定的参考价值。
B/S中一般通信和WebSocket的区别:
在B/S结构的应用中,传统的通信机制是请求-响应的模式,也就是说只有客户端发送请求,服务端才会给出相应的响应(不考虑程序问题或者是其他原因),服务器不能够主动的为浏览器推送消息。但是WebSocket可以实现客户端和服务端的双向通信,其原理就是在客户端和服务器端建立一个通信的管道,来实现客户端和服务器端的双向通信。
通过在写例子的过程中,我的理解是(Java为例-注解方式):服务器端通过注解为方法注册监听事件(项目启动会自动扫描这些注解然后进行装载配置),然后客户端通过绑定到WebSocket对象上的方法共同实现客户端和服务器端的消息传输(简单理解)。
①服务端配置
1 package com.chat.config; 2 3 import java.util.Set; 4 import javax.websocket.Endpoint; 5 import javax.websocket.server.ServerApplicationConfig; 6 import javax.websocket.server.ServerEndpointConfig; 7 8 public class WebSocketConfig implements ServerApplicationConfig{ 9 10 /** 11 * 基于注解的开启方式 12 */ 13 @Override 14 public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanedSockets) { 15 System.out.println("========================="); 16 System.out.println(" WebSocket装载配置..."); 17 System.out.println("========================="); 18 return scanedSockets; 19 } 20 21 /** 22 * 结余接口的开启方式 23 */ 24 @Override 25 public Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> arg0) { 26 return null; 27 } 28 29 }
②服务端Socket
1 package com.chat.socket; 2 3 import java.io.IOException; 4 import java.io.UnsupportedEncodingException; 5 import java.net.URLDecoder; 6 import java.util.ArrayList; 7 import java.util.Iterator; 8 import java.util.List; 9 10 import javax.websocket.OnClose; 11 import javax.websocket.OnMessage; 12 import javax.websocket.OnOpen; 13 import javax.websocket.Session; 14 import javax.websocket.server.ServerEndpoint; 15 16 import com.chat.message.Message; 17 18 @ServerEndpoint("/chat") 19 public class ChatSocket { 20 21 private static List<String> names = new ArrayList<String>(); 22 private static List<Session> sessions = new ArrayList<Session>(); 23 //当前登录用户 24 private static String userName ; 25 26 /** 27 * 每一个通信管道对应一个Socket实例,也是一个Session 28 */ 29 public ChatSocket () { 30 System.out.println("ChatSocket 创建完成."); 31 } 32 33 /** 34 * 会话开启事件 35 * @param session 36 */ 37 @OnOpen 38 public void chatOpen (Session session) { 39 this.userName = session.getQueryString(); 40 try { 41 userName = URLDecoder.decode(userName, "utf-8"); 42 if (null != userName && !userName.isEmpty()) { 43 userName = userName.split("=")[1].trim(); 44 String msgStr = "欢迎" + userName + "加入聊天室!"; 45 names.add(userName);//用户列表 46 Message msg = new Message(); 47 msg.setNames(names); 48 msg.setMsg(msgStr); 49 sessions.add(session); 50 broadcast(msg); 51 } 52 } catch (Exception e) { 53 e.printStackTrace(); 54 } 55 } 56 57 /** 58 * 处理客户端发送的消息并响应 59 * @param session 60 * @param msg 客户端发送的消息体 61 */ 62 @OnMessage 63 public void ChatMsg (Session session,String msg) { 64 String msgBody = "【" + this.userName + "】说:</br>" + msg; 65 Message msgObj = new Message(); 66 msgObj.setMsg(msgBody); 67 msgObj.setNames(names); 68 //广播客户端消息给每个登录用户 69 this.broadcast(msgObj); 70 } 71 72 /** 73 * 会话关闭事件 74 */ 75 @OnClose 76 public void close (Session session) { 77 String msg = "欢送 " + this.userName + " 离开聊天室!"; 78 //移除当前推出的会话(管道) 79 sessions.remove(session); 80 Message msgObj = new Message(); 81 names.remove(this.userName); 82 msgObj.setMsg(msg); 83 msgObj.setNames(names); 84 this.broadcast(msgObj); 85 } 86 87 /** 88 * 消息广播的方法 89 * @param msg 90 */ 91 public void broadcast(Message msg) { 92 for (Iterator<Session> sessionIt = sessions.iterator();sessionIt.hasNext();) { 93 try { 94 sessionIt.next().getBasicRemote().sendText(msg.toJson()); 95 System.out.println(msg.toJson()); 96 } catch (IOException e) { 97 e.printStackTrace(); 98 } 99 } 100 } 101 }
③格式化消息体
1 package com.chat.message; 2 3 import java.util.List; 4 5 import com.google.gson.Gson; 6 7 public class Message { 8 9 private List<String> names; 10 private String msg; 11 12 private static Gson gson = new Gson(); 13 14 public List<String> getNames() { 15 return names; 16 } 17 public void setNames(List<String> names) { 18 this.names = names; 19 } 20 public String getMsg() { 21 return msg; 22 } 23 public void setMsg(String msg) { 24 this.msg = msg; 25 } 26 27 public String toJson () { 28 return gson.toJson(this); 29 } 30 31 }
④应用-登录
1 package com.chat.servlet; 2 3 import java.io.IOException; 4 import java.io.PrintWriter; 5 6 import javax.servlet.ServletException; 7 import javax.servlet.annotation.WebServlet; 8 import javax.servlet.http.HttpServlet; 9 import javax.servlet.http.HttpServletRequest; 10 import javax.servlet.http.HttpServletResponse; 11 import javax.servlet.http.HttpSession; 12 13 14 @WebServlet("/loginServlet") 15 public class LoginServlet extends HttpServlet { 16 private static final long serialVersionUID = 1L; 17 18 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 19 this.doPost(request, response); 20 } 21 22 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 23 String userName = null == request.getParameter("userName") ? "" : request.getParameter("userName").trim(); 24 HttpSession session = request.getSession(); 25 if (!userName.isEmpty()) { 26 session.setAttribute("userName", userName); 27 } 28 response.sendRedirect("jsp/chat.jsp"); 29 } 30 }
⑤客户端-登录页面
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 <title>Login Page</title> 8 </head> 9 <body> 10 11 <form action="${pageContext.request.contextPath}/loginServlet" method="get"> 12 UserName:<input type="text" name="userName"/> 13 <br/> 14 <input type="submit" value="Submit"/> 15 </form> 16 </body> 17 </html>
⑥客户端-聊天页面
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 <title>Chat Page</title> 8 <script type="text/javascript" src="${pageContext.request.contextPath}/plugins/jquery-1.8.3.min.js"></script> 9 <script type="text/javascript"> 10 //声明全局变量 11 var ws; 12 var userName = ‘${sessionScope.userName}‘; 13 var target = "ws://localhost:9999/ChatDemo/chat?userName=" + userName; 14 $(function () { 15 //打开页面就开启Socket连接 16 if (‘WebSocket‘ in window) { 17 ws = new WebSocket(target); 18 } else if (‘MozWebSocket‘ in window) {//火狐 19 ws = new MozWebSocket(target); 20 } else { 21 return alert("请使用支持WebSocket的浏览器!"); 22 } 23 ws.onmessage = function (event) { 24 if (event) { 25 console.dir(event); 26 $("#userList").html(""); 27 eval("var data = " + event.data + ";"); 28 $(data.names).each(function () { 29 $("#userList").append(this + "</br>"); 30 }); 31 $("#chatContent").append(data.msg + "<br/>"); 32 } 33 } 34 //为send按钮增加点击事件(发送消息按钮) 35 $("#sendBtn").on("click",function () { 36 //获取需要发送的消息体 37 var msgEdit = $("input[name=‘sendMsg‘]").val(); 38 ws.send(msgEdit); 39 $("input[name=‘sendMsg‘]").val(""); 40 }); 41 }); 42 </script> 43 <style type="text/css"> 44 45 </style> 46 </head> 47 <body> 48 <div id="chatContent" style="float:left;width:267px;height:240px;border:1px solid black;"> 49 </div> 50 51 <div id="userList" style="float:left;width:112px;height:240px;border:1px solid black;"> 52 </div> 53 <div id="msgSendContent" style="clear: both;"> 54 <input type="text" name="sendMsg" /><button id="sendBtn">Send</button> 55 </div> 56 </body> 57 </html>
例子结构(非Maven)
以上是关于WebSocket 实现群聊 - 简单测试例子的主要内容,如果未能解决你的问题,请参考以下文章
推荐一个.Net Core开发的Websocket群聊私聊的开源项目
spring websocket 和socketjs实现单聊群聊,广播的消息推送详解
代码发布项目——django实现websocket(使用channels)基于channels实现群聊功能gojs插件paramiko模块