1.网络通信协议

  • TCP协议
    TCP协议是一种面向连接的协议,就是在通信之前需要先建立连接。举个列子,就像打电话一样,需要对方先接通,才能进行通话。
  • UDP协议
    UDP是面向无连接的协议,在通信的时候不需要建立连接,只需要直接将数据发出即可。
  • 安全性分析
    两者相比,TCP更加安全,更加可靠,TCP提供可靠传输服务,无差错,不丢失,不重复。UDP通信则可靠性低,因为是无连接的,同时不管信息是否已经传输成功,芷尽最大努力实现交付。
  • 效率比较
    TCP相对来说效率较低
    UDP传输效率更高,适用于高速传输和实时传输。

2.WebSocket

  • 什么是webSocket?
    WebSocket是一中在TCP连接上进行全双工通信的协议。
  • 什么是全双工通信
    在通信时双方可同时进行信息的传输,不需要等待另一方传输完毕再进行传输。

3.主要代码

  • 主要前端代码
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>聊天室</title><script src="/jquery.js" type="text/javascript"></script><style>#message{width: 910px;height: 610px;}#box{float: left;width: 600px;height: 610px;display: none;}#box1{float: left;background-color: gray;width: 300px;height: 600px;}#chatArea{width: 600px;height: 300px;background-color: gainsboro;}#sendArea{width: 600px;height: 300px;background-color: coral;}#content{width: 500px;}#haoyou{height: 300px;}#userList{list-style: none;}#broadList{list-style: none;}#msgRight{width: 100%;text-align: right;color: coral;}#msgLeft{width: 100%;color: aqua;}</style><script>var toName;var username;function showCat(name){toName = name;//现在聊天对话框$("#box").css("display","block");//清空聊天区$("#chatArea").html("");$("#chatMes").html("正在和<font face=\"楷体\">"+toName+"</font>聊天");//存储聊天记录 sessionStorgevar chatData = sessionStorage.getItem(toName);if(chatData != null){//将聊天记录渲染到聊天去$("#chatArea").html(chatData);}}$(function (){$.ajax({url:"/user/getUsername",success:function (res){username = res;// $("#username").html("用户:"+res+"<span style='float: right;color: green'>在线</span>");},async:false});if("WebSocket" in window){//创建一个websocketvar ws = new WebSocket("ws://localhost:8080/chat");}else{alert("该浏览器不支持websocket");}//给ws绑定事件ws.onopen = function (){//在建立连接后需要做什么事?//1.显示在线信息$("#username").html("用户:"+username+"<span style='float: right;color: green'>在线</span>");}//接收到服务端推送的消息后,触发这个事件ws.onmessage = function (evt){//获取服务端推送过来的消息var dataStr = evt.data;//将dataStr转换为json对象var res = JSON.parse(dataStr);console.log(res);//判断是否时系统消息if(res.system){//系统消息//1.好友列表展示//2.系统广播展示var names = res.message;var userListStr = "";var broadListStr = "";for (var name of names) {if(name != username){userListStr += "<li><a οnclick='showCat(\""+name+"\")'>"+name+"</a></li>";broadListStr +="<li>您的好友"+name+"已上线</li>";}}//渲染好友列表和广播$("#userList").html(userListStr);$("#broadList").html(broadListStr);}else{//不是系统消息//将服务端推送的消息进行展示var str = " <div id=\"msgLeft\">"+res.message+"</div>"if(toName != res.fromName){$("#chatArea").append(str);}$("#chatArea").append(str)//存储数据var chatData = sessionStorage.getItem(res.fromName);if(chatData != null){//拿到聊天记录str = chatData+str;}sessionStorage.setItem(res.fromName,str);}}ws.onclose = function (){$("#username").html("用户:"+username+"<span style='float: right;color: red'>离线</span>");}//点击发送按钮$("#send").click(function (){//获取输入的内容var data = $("#content").val();//清空输入区的内容$("#content").val("");//将消息数据展示在聊天区var str = "<div id=\"msgRight\">"+data+"</div>"$("#chatArea").append(str);var json = {"toName":toName,"message":data};//将聊天内容保存//先拿到用户,看是否存在聊天记录//如果不存在聊天记录,将将当前的聊天存起来var chatData = sessionStorage.getItem(toName);if(chatData != null){//拿到聊天记录str = chatData+str;}sessionStorage.setItem(toName,str);//将数据发送给服务端ws.send(JSON.stringify(json));})})</script>
</head>
<body><span id="username"></span><div id="message"><div id="box"><span id="chatMes"></span><div id="chatArea"></div><div id="sendArea"><textarea id="content"></textarea><button id="send">发送</button></div></div><div id="box1"><div id="haoyou"><span style="background-color: aqua;font-size: 20px">好友列表</span><ul id="userList"></ul></div><div><span style="background-color: aqua;font-size: 20px">广播列表</span><ul id="broadList"></ul></div></div></div></body>
</html>
  • 主要的后端代码
    实体类
package com.dfc.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class Message {private String toName;private String message;
}
package com.dfc.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;//登录使用
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result {private boolean flag;private String message;
}package com.dfc.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResultMessage {private boolean isSystem;private String fromName;private Object message;//如果是系统推送消息是数组
}package com.dfc.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private String username;private String password;
}

controller层

package com.dfc.controller;import com.dfc.pojo.Result;
import com.dfc.pojo.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpSession;@RestController
@RequestMapping("/user")
public class UserController {@RequestMapping("/login")public Result login(User user, HttpSession session){Result result = new Result();if(user != null && "123".equals(user.getPassword())){result.setFlag(true);//将用户保存到session中session.setAttribute("user",user.getUsername());}else{result.setFlag(false);result.setMessage("登录失败");}return result;}@RequestMapping("/getUsername")public String getUsername(HttpSession session){String username = (String) session.getAttribute("user");return username;}
}

WebSocket主要实现代码

package com.dfc.ws;import com.dfc.pojo.Message;
import com.dfc.utils.MessageUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;@ServerEndpoint(value="/chat",configurator = GetHttpSessionConfigurator.class)@Component
public class ChatEndpoint {//定义一个对象用来存储客户端对象对应的ChatEndpoint  双列private static Map<String,ChatEndpoint> onlineUsers = new ConcurrentHashMap<>();//声明session对象,通过该对象可以发送消息给指定用户private Session session;//声明一个HttpSession对象,因为我们之前在HttpSession中存储了用户名private HttpSession httpSession;//连接建立时被调用@OnOpenpublic void onOpen(Session session, EndpointConfig config){//将局部session对象赋值给成员sessionthis.session = session;//获取HttpSession对象HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());this.httpSession = httpSession;//从httpSession对象中获取用户名String username = (String) httpSession.getAttribute("user");//将当前对象存储到容器中onlineUsers.put(username,this);//将当前在线用户名推送给所有的客户端//1.获取消息String message = MessageUtils.getMessage(true,null,getNames());//2.调用方法进行系统消息的推送broadAllUsers(message);}//从onlineUsers中得到在线用户名字private Set<String> getNames(){return onlineUsers.keySet();}private void broadAllUsers(String message){try{//要将该消息推送给所有的客户端Set<String> names = onlineUsers.keySet();for (String name : names) {ChatEndpoint chatEndpoint = onlineUsers.get(name);chatEndpoint.session.getBasicRemote().sendText(message);}}catch (Exception e){e.printStackTrace();}}//接收到客户端发送的数据被调用@OnMessagepublic void onMessage(String message,Session session){//将message转换成message对象ObjectMapper mapper = new ObjectMapper();try {Message mess = mapper.readValue(message, Message.class);//获取接收数据的用户String toName = mess.getToName();//获取消息数据String data = mess.getMessage();//获取当前登录的用户String username = (String) httpSession.getAttribute("user");//获取推送给指定用户的消息格式的数据String resultMessage = MessageUtils.getMessage(false,username,data);//发送数据onlineUsers.get(toName).session.getBasicRemote().sendText(resultMessage);} catch (Exception e) {e.printStackTrace();}}//连接关闭时被调用@OnClosepublic void onClose(Session session){String username = (String) httpSession.getAttribute("user");//处理用户已经下线//从容器中删除指定的用户onlineUsers.remove(username);//获取推送的消息String message = MessageUtils.getMessage(true,null,getNames());broadAllUsers(message);}
}//需要将这个类托管给spring来管理
package com.dfc.ws;import lombok.val;import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;public class GetHttpSessionConfigurator extends ServerEndpointConfig.Configurator {@Overridepublic void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {HttpSession httpSession = (HttpSession) request.getHttpSession();//将httpSession对象存储到配置对象中sec.getUserProperties().put(HttpSession.class.getName(),httpSession);}
}//消息处理工具类
package com.dfc.utils;import com.dfc.pojo.ResultMessage;
import com.fasterxml.jackson.databind.ObjectMapper;public class MessageUtils {public static String getMessage(boolean isSystemMessage,String fromName,Object message){try {ResultMessage resultMessage = new ResultMessage();resultMessage.setSystem(isSystemMessage);resultMessage.setMessage(message);if(fromName != null){resultMessage.setFromName(fromName);}ObjectMapper mapper = new ObjectMapper();return mapper.writeValueAsString(resultMessage);}catch (Exception e){e.printStackTrace();}return null;}
}

4.效果展示

再浏览器中登录一个用户名为 123的用户,这是自己的用户名,然后再用另一个浏览器登录另一个账户,将会再好友列表中展示处已经上线的用户。这是服务器推送的广播消息

之后点击想要发送消息的用户就可以发送消息了
页面做的比较丑,请忽略
做了一个稍微能看的下去的
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201115212726176.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMDI0OTI1,size_16,color_FFFFFF,t_70#pic_center

代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>D-F</title><script src="js/jquery.js"></script><style>#box{display: flex;flex-direction: row;}#userList{width: 140px;height: 600px;border-radius: 10px;border: 1px solid gainsboro;}#chatArea{width: 300px;height: 600px;border-radius: 10px;border: 1px solid gainsboro;}#boradArea{width: 200px;height: 600px;border-radius: 10px;border: 1px solid gainsboro;}#userList-head{display: flex;flex-direction: row;align-items: center;border-radius: 10px;background-color: antiquewhite;    }#boradArea-head{display: flex;flex-direction: row;/* width: 100%;height: 20px; */border-radius: 10px;align-items: center;background-color: antiquewhite;box-sizing: border-box;   }#userList-head img{width: 17px;height: 17px;}#common{display: none;width: 140px;height: 583px;border-radius: 10px;}#userInfo{background-color: antiquewhite;border-radius: 10px;text-align: center;}/* 聊天区域 */#chatContent{width: 100%;height: 450px;/* border-bottom:1px solid black; */}#right{width: 100%;display: flex;justify-content: end;}#right-item img{width: 20px;height: 20px;}/* 接收消息展示 */#left{width: 100%;display: flex;justify-content: start;}#left-item img{width: 20px;height: 20px;}#message-box{display: flex;flex-direction: row;background-color: rgb(252, 251, 251);}#message{width: 80%;height: 30px;border-radius: 20px;}#submit{width: 15%;height: 20px;margin-top: 8px;background-color: rgb(48, 250, 48);text-align: center;border-radius: 20px;}#diy{display: flex;flex-direction: row;justify-content: space-around;background-color: rgb(252, 251, 251);}#diy-item{margin-top: 20px;display: flex;flex-direction: column;align-items: center;}#diy-item img{width: 20px;height: 20px;}/* 展示好友列表 */#flist{list-style: none;line-height: 40px;}#flist a{text-decoration: none;}#myfont{position: fixed;width: 200px;height: 100px;background-color: azure;top: 350px;left: 200px;display: none;}</style><script>//点击好友进行聊天function show(name){$("#name").html(name);$("#action").css("display","block");$("#other").css("display","none");}//弹出显示框function change(index){if(index == 1){$("#myfont").css("display","block");  }}$(function(){var flag = true;$("#down").click(function(){if(flag){//获取下拉图标id$("#common").css("display","block");$("#down").attr("src","img/up.png");flag = false;}else{//点击上拉按钮收回好友列表$("#common").css("display","none");$("#down").attr("src","img/down.png");flag = true;}});//点击返回返回首页$("#back").click(function(){$("#action").css("display","none");$("#other").css("display","block");});//点击改变字体$("#commit").click(function(){var data = $("#fontValue").val();$("#myfont").css("display","none");  $("#msg").css("font-size",data+"px");$("#msg1").css("font-size",data+"px");})});</script>
</head>
<body><div id="box"><div id="userList"><div id="userList-head"><span id="title">在线好友</span><img src="img/down.png"/ id="down"></div><!-- 展示好友列表 --><div id="common"><ul id="flist"><li><img src="img/girl.png" style="width: 20px;height: 20px;" alt=""><a onclick="show('张三丰')">张三丰</a></li><li><img src="img/girl.png" style="width: 20px;height: 20px;" alt=""><a onclick="show('张无忌')">张无忌</a></li><li><img src="img/girl.png" style="width: 20px;height: 20px;" alt=""><a onclick="show('赵无极')">赵无极</a></li><li><img src="img/girl.png" style="width: 20px;height: 20px;" alt=""><a onclick="show('赵敏')">赵敏</a></li><li><img src="img/girl.png" style="width: 20px;height: 20px;" alt=""><a onclick="show('迪丽热巴')">迪丽热巴</a></li><li><img src="img/girl.png" style="width: 20px;height: 20px;" alt=""><a onclick="show('邓超')">邓超</a></li></ul></div></div><div id="chatArea"><!-- 聊天区域 --><!-- 聊天头部 --><div id="action"  style="display: none;"><div id="userInfo"><img src="img/back.png" style="width: 20px;height:20px; float: left;" id="back"/>正在和<font style="font-weight:200;color: chartreuse;" id="name"></font>聊天</div><div id="chatContent"><div id="right"><div id="right-item"><span id="msg">你好</span><img src="img/boy.png"/></div></div><div id="left"><div id="left-item"><img src="img/girl.png"/><span id="msg1">你好</span></div></div></div><!-- 消息输入框 --><div id="message-box"><textarea id="message"></textarea><div id="submit">发送</div></div><!-- 用户自定义选项 --><div id="diy"><div id="diy-item" onclick="change(1)"><img src="img/font.png"/><span>字体</span></div><div id="diy-item" onclick="change(2)"><img src="img/pifu.png"/><span>颜色</span></div><div id="diy-item" onclick="change(3)"><img src="img/add.png"/><span>更多</span></div></div></div><!-- 没有进行聊天的时候展示页面--><div id="other">欢迎来到D-f聊天室</div><!-- 选择字体 --><div id="myfont"><input type="number" max="40" min="5" id="fontValue" placeholder="输入字体大小"/><input type="submit" value="确认" id="commit"/></div></div><div id="boradArea"><div id="boradArea-head"><span id="title">广播消息</span></div></div></div>
</body>
</html>

`

SpringBoot整合WebSocket实现聊天室系统相关推荐

  1. 在线聊天室的消息单聊的实现——springboot整合WebSocket(二)

    一.声明 项目的搭建请大家移步到:在线聊天室的消息群聊的实现--springboot整合WebSocket(一) 单聊的实现是在群聊项目上进行延申改造的. 二.引入依赖 <dependency& ...

  2. SpringBoot + Vue 实现基于 WebSocket 的聊天室(单聊)

    前言 在前一篇文章SpringBoot 集成 STOMP 实现一对一聊天的两种方法中简单介绍了如何利用 STOMP 实现单聊,本文则将以一个比较完整的示例展示实际应用,不过本文并未使用 STOMP,而 ...

  3. SpringBoot整合websocket实现在线客服聊天

    websocket最伟大之处在于服务器和客户端可以在给定的时间范围内的任意时刻,相互推送信息. 浏览器和服务器只需要要做一个握手的动作,在建立连接之后,服务器可以主动传送数据给客户端,客户端也可以随时 ...

  4. Springboot 整合Websocket+Stomp协议+RabbitMQ做消息代理 实例教程

    前言 如果你还没有了解过websocket,关于整合websocket的简单入门使用,可以先看看我这篇: <SpringBoot 整合WebSocket 简单实战案例> https://b ...

  5. 技术干货 | 网易云信大规模聊天室系统架构解析

    导读:聊天室是一类非常重要的 IM 系统,不同于单聊和群聊,聊天室是一种大规模的实时消息分发系统.本文我们来详细介绍一下网易云信大规模聊天室系统的具体架构以及实践应用案例. 文|曹佳俊 网易云信资深服 ...

  6. 【Spring Web教程】SpringBoot 整合WebSocket

    概括 WebSocket是一种服务端和网页之间的通讯协议,服务端跟网页保持着长连接,可以达到服务端主动给网页发消息的功能. 常用场景:Web聊天室.通知和紧急告警.网页消息通信.物联网通讯. Spri ...

  7. 视频教程-基于Java的WebSocket的聊天室-Java

    基于Java的WebSocket的聊天室 多年 Java 企业级应用开发工作经验,曾参与中国人寿.华夏人寿.泰康人寿.信达财险等保险行业内部业务管理系统以及线上在线产品的开发:参与中国人民银行.清华大 ...

  8. SpringBoot 整合WebSocket 简单实战案例

    前言 这个简单实战案例主要目的是让大家了解websocket的一些简单使用. 另外使用stomp方式的: <Springboot 整合 WebSocket ,使用STOMP协议 ,前后端整合实战 ...

  9. 【毕业设计之PHP系列】基于PHP的网络聊天室系统

    基于PHP的网络聊天室系统 摘要:我们生活在一个通信变得非常重要的世界里,人们需要同他人快速容易的进行交流.E-mail.电话.邮件以及在线聊天是以书写文字的形式让人们进行思想交流的媒体.通信时一个重 ...

  10. Python用tornado的websocket开发聊天室

    Python用tornado的websocket开发聊天室 用tornado开发基于异步websocket聊天室-demo 目录结构 Python包 main.py app/views.py temp ...

最新文章

  1. php 静态类在worker,GatewayWorker的Events.php中调用Worker::runAll()出现异常
  2. DGA域名可以是色情网站域名
  3. Ubuntu 16.04下Caffe-SSD的应用(一)——编译Caffe-SSD的CPU版本与GPU版本
  4. ip中继对接_鼎信通达MTG系列-语音中继网关,可和VOS,IPPBX,SIP网关进行对接
  5. pwntools常用脚本语句介绍讲解
  6. Java基础之重写与重载深入解析
  7. ECMAScript 2015~2020 语法全解析
  8. 【数据结构与算法】顺序表V3.0的Java实现
  9. 从Spring代理的bean中获取代理对象
  10. 记一次设置密钥登陆centos7所遇问题
  11. atitit.按钮光标滑过高亮切换以及其他动态效果的实现css html js --attilax总结
  12. 搭建Linux的基础命令符---bc
  13. 中兴设备交换机路由器清除清理指定接口计数的统计信息命令
  14. 使用SVN将项目从服务器下载到本地
  15. Android 11.0 12.0默认开启开发者模式和开启usb调试模式
  16. 二十一、常见股票和量化投资策略
  17. No way to dispatch this command to Redis Cluster because keys have different slots.
  18. 用 FFMPEG 合并 MP4 视频
  19. pads layout查看管脚连接
  20. VS6 sp6补丁下载 [防VC6卡死]

热门文章

  1. 【考研】哈尔滨工业大学计算机考研854复习资料
  2. 使用SCCM管理Office ProPlus(二)--升级最到最新更新
  3. 安装office未能启动服务器,Office 2010安装时遇到1920错误问题怎么解决?
  4. 微信查询对账单对账+数据读取解析入库
  5. QT error: undefined reference to `__imp__ZN12QSqlDatabase7driversEv‘报错
  6. 老路用得上的商学课-61-80学习(读书)笔记
  7. 使用http://rap2.taobao.org/写测试接口文档
  8. 云解析DNS使用教程
  9. GitHub使用指南
  10. 面经-应届生秋招上岸笔记(低难度 带项目版)