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 }

WebSocketConfig.java

  ②服务端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 }

ChatSocket.java

  ③格式化消息体

 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 }

Message.java

  ④应用-登录

 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 }

LoginServlet.java

  ⑤客户端-登录页面

 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>

login.jsp

  ⑥客户端-聊天页面

 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>

chat.jsp

例子结构(非Maven)

原文地址:https://www.cnblogs.com/simpleJokerKing/p/8849059.html

时间: 2024-08-01 10:06:16

WebSocket 实现群聊 - 简单测试例子的相关文章

Swoole实现基于WebSocket的群聊私聊

本文属于入门级文章,大佬们可以绕过啦.如题,本文会实现一个基于Swoole的websocket聊天室(可以群聊,也可以私聊,具体还需要看数据结构的设计). 搭建Swoole环境 通过包管理工具 # 安装依赖包 $ sudo apt-get install libpcre3 libpcre3-dev # 安装swoole $ pecl install swoole # 添加extension拓展 $ echo extension=swoole.so > /etc/php5/cli/conf.d/s

Flask 实现 WebSocket 通讯---群聊和私聊

一.WebSocket介绍 WebSocket是一种在单个TCP连接实现了服务端和客户端进行双向文本或二进制数据通信的一种通信的协议. WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据.在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输. 一次请求 - 服务器收到请求 开始和客户端握手 - 保持长连接 - 数据实时 - 连接永远保持 优点:长连接 并且不影响 收发请求 缺点:连接保

websocket实现群聊和单聊(转)

昨日内容回顾 1.Flask路由 1.endpoint="user" # 反向url地址 2.url_address = url_for("user") 3.methods = ["GET","POST"] # 允许请求进入视图函数的方式 4.redirect_to # 在进入视图函数之前重定向 5./index/<nid> # 动态参数路由 <int:nid> def index(nid) 6.str

Android中脱离WebView使用WebSocket实现群聊和推送功能

WebSocket是Web2.0时代的新产物,用于弥补HTTP协议的某些不足,不过他们之间真实的关系是兄弟关系,都是对socket的进一步封装,其目前最直观的表现就是服务器推送和聊天功能.更多知识参考:如何理解 TCP/IP, SPDY, WebSocket 三者之间的关系? 今天的重点是讲如何在Android中脱离WebView使用WebSocket,而不是在Web浏览器使用,如果是在Web浏览器中使用,网上已经太多教程.框架和demo,没必要讲. 到目前为止我个人认为安卓端比较好用的WebS

Socket通信 简单实现私聊、群聊(dos命令下)

很久以前的一个Demo,这里服务器只做转发功能,根据ID地址和端口号来标识身份,群聊和私聊只是简单实现, 服务器代码如下: import java.util.*; import java.io.*; import java.net.*; public class Server extends Thread { private static Vector<Socket> vecClient = new Vector<Socket>(); private PrintWriter out

spring websocket 和socketjs实现单聊群聊,广播的消息推送详解

spring websocket 和socketjs实现单聊群聊,广播的消息推送详解 WebSocket简单介绍 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展了浏览器与服务端的通信功能,使服务端也能主动向客户端发送数据. 我们知道,传统的HTTP协议是无状态的,每次请求(request)都要由客户端(如 浏览器)主动发起,服务端进行处理后返回response结果,而

代码发布项目(二)——django实现websocket(使用channels)、基于channels实现群聊功能、gojs插件、paramiko模块

一.django实现websocket django默认是不支持websocket,只支持http协议 在django中如果想要基于websocket开发项目 你需要安装模块:channles pip3 install channels==2.3 版本不要使用最新的,如果安装最新的可能会自动把你的django版本升级到最新版 对应的解释器环境建议使用3.6(官网的说法:3.5可能有问题,3.7可能也有问题...具体原因没有给解释) channels模块内部已经帮我们封装好了 握手/加密/解密 面

centos7搭建ELK Cluster集群日志分析平台(四):简单测试

续之前安装好的ELK集群 各主机:es-1 ~ es-3 :192.168.1.21/22/23 logstash: 192.168.1.24 kibana: 192.168.1.25 测试机:client: 192.168.1.26 在测试机上安装并启动filebeat 1. 下载filebeat  ~]# wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-5.4.0-linux-x86_64.tar.gz

websocket 群聊,单聊,加密,解密

群聊 from flask import Flask, request, render_templatefrom geventwebsocket.handler import WebSocketHandlerfrom gevent.pywsgi import WSGIServer from geventwebsocket.websocket import WebSocket app = Flask(__name__) # type:Flask user_socket_list = [] @app