目录

一、认识Websocket

1、什么是websocket

2、websocket优势分析

3、websocket与springboot应用程序交互的图解

4、websocket与http协议对比

二、Springboot实现websocket技术的案例

1、引入依赖

2、注入IOC容器

3、websocket服务类

三、前端websocket连接

1、websocket连接的js

2、在线访问的html

四、代码设计与测试

1、失败重连

2、心跳检测

3、用户在线聊天测试

五、案例源码


一、认识Websocket

1、什么是websocket

WebSocket是一种在单个TCP连接上进行全双工通信的协议。

全双工:可以同时双向传输数据(B->A,A->B可以同时进行)。

推送技术是建立在客户端服务器的一种机制,就是由服务器主动将信息发往客户端的技术。就像广播电台播音。

2、websocket优势分析

过去传统的服务器与客户端的聊天通信一般有两种:

1、轮询请求:通过http的短连接的方式来进行轮询请求,不断轮询请求,对服务器压力很大。

2、socket长连接:socket长连接保证了客户端和服务器的长连接通信,但对服务器资源照成了极大的浪费。

于是诞生了websocket技术。

websocket协议的实现方式:

它是一种长连接,只能通过一次请求来初始化连接,然后所有的请求和响应都是通过这个TCP连接进行通讯,这意味着它是基于事件驱动,异步的消息机制。

3、websocket与springboot应用程序交互的图解

4、websocket与http协议对比

二、Springboot实现websocket技术的案例

1、引入依赖

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>

2、注入IOC容器

@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter(){return new ServerEndpointExporter();}
}

3、websocket服务类

package com.dragonwu.config.websocket;import com.alibaba.fastjson2.JSON;
import org.springframework.stereotype.Component;import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;/*** @author Dragon Wu* @since 2022-10-12 19:11**/
//ws://localhost:port/websocket/A
@ServerEndpoint(value = "/websocket/{userId}")
@Component
public class WebSocketEndpoint {//与某个客户端的连接会话,需要通过它来给客户端发生数据private Session session;/*连接建立成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathParam("userId") String userId){//把会话存入到连接池中SessionPool.sessions.put(userId,session);}/*关闭连接*/@OnClosepublic void onClose(Session session) throws IOException {SessionPool.close(session.getId());session.close();}/*收到客户端消息后调用的方法*/@OnMessagepublic void onMessage(String message,Session session){// 如果是心跳检测的消息,则返回pong作为心跳回应if (message.equalsIgnoreCase("ping")) {try {Map<String, Object> params = new HashMap<String, Object>();params.put("type", "pong");session.getBasicRemote().sendText(JSON.toJSONString(params));System.out.println("应答客户端的消息:" + JSON.toJSONString(params));} catch (Exception e1) {e1.printStackTrace();}}else{SessionPool.sendMessage(message);}}}

线程池操作类:

package com.dragonwu.config.websocket;import javax.websocket.Session;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** @author Dragon Wu* @since 2022-10-12 19:19**/
public class SessionPool {//sessionId为系统随机生成的public static Map<String, Session> sessions = new ConcurrentHashMap<>();public static void close(String sessionId) throws IOException {for (String userId : SessionPool.sessions.keySet()) {Session session = SessionPool.sessions.get(userId);if (session.getId().equals(sessionId)) {sessions.remove(userId);break;}}}public static void sendMessage(String sessionId, String message) {sessions.get(sessionId).getAsyncRemote().sendText(message);}public static void sendMessage(String message) {for (String sessionId : SessionPool.sessions.keySet()) {SessionPool.sessions.get(sessionId).getAsyncRemote().sendText(message);}}public static void sendMessage(Map<String, Object> params) {//{"formUserId":userId,"toUserId":toUserId,"msg":msg}String toUserId = params.get("toUserId").toString();String msg = params.get("msg").toString();String fromUserId = params.get("fromUserId").toString();msg = "来自" + fromUserId + "的消息:" + msg;Session session = sessions.get(toUserId);if (session != null) {session.getAsyncRemote().sendText(msg);}}
}

三、前端websocket连接

1、websocket连接的js

var wsObj = null;
var wsUri = null;
var userId = -1;
var lockReconnect = false;
var wsCreateHandler = null;
function createWebSocket() {var host = window.location.host; // 带有端口号userId = GetQueryString("userId");// wsUri = "ws://" + host + "/websocket?userId=" + userId;wsUri = "ws://" + host + "/websocket/" + userId;try {wsObj = new WebSocket(wsUri);initWsEventHandle();} catch (e) {writeToScreen("执行关闭事件,开始重连");reconnect();}
}function initWsEventHandle() {try {wsObj.onopen = function (evt) {onWsOpen(evt);heartCheck.start();};wsObj.onmessage = function (evt) {onWsMessage(evt);heartCheck.start();};wsObj.onclose = function (evt) {writeToScreen("执行关闭事件,开始重连");onWsClose(evt);reconnect();};wsObj.onerror = function (evt) {writeToScreen("执行error事件,开始重连");onWsError(evt);reconnect();};} catch (e) {writeToScreen("绑定事件没有成功");reconnect();}
}function onWsOpen(evt) {writeToScreen("CONNECTED");
}function onWsClose(evt) {writeToScreen("DISCONNECTED");
}function onWsError(evt) {writeToScreen(evt.data);
}function writeToScreen(message) {if(DEBUG_FLAG){$("#debuggerInfo").val($("#debuggerInfo").val() + "\n" + message);}
}function GetQueryString(name) {var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");var r = window.location.search.substr(1).match(reg); //获取url中"?"符后的字符串并正则匹配var context = "";if (r != null)context = r[2];reg = null;r = null;return context == null || context == "" || context == "undefined" ? "" : context;
}//断后重连
function reconnect() {if(lockReconnect) {return;};writeToScreen("1秒后重连");lockReconnect = true;//没连接上会一直重连,设置延迟避免请求过多wsCreateHandler && clearTimeout(wsCreateHandler);wsCreateHandler = setTimeout(function () {writeToScreen("重连..." + wsUri);createWebSocket();lockReconnect = false;writeToScreen("重连完成");}, 1000);
}//心跳检测
var heartCheck = {//15s之内如果没有收到后台的消息,则认为是连接断开了,需要再次连接timeout: 15000,timeoutObj: null,serverTimeoutObj: null,//重启reset: function(){clearTimeout(this.timeoutObj);clearTimeout(this.serverTimeoutObj);this.start();},//开启定时器start: function(){var self = this;this.timeoutObj && clearTimeout(this.timeoutObj);this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);this.timeoutObj = setTimeout(function(){writeToScreen("发送ping到后台");try{wsObj.send("ping");}catch(ee){writeToScreen("发送ping异常");}//内嵌计时器self.serverTimeoutObj = setTimeout(function(){//如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次writeToScreen("没有收到后台的数据,关闭连接");//wsObj.close();reconnect();}, self.timeout);},this.timeout)},
}

2、在线访问的html

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>Floor View</title><script src="/js/websocket.js"></script><script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script><script id="code">var DEBUG_FLAG = true;$(function(){//启动websocketcreateWebSocket();});// 当有消息推送后触发下面事件function onWsMessage(evt) {var jsonStr = evt.data;writeToScreen(jsonStr);}function writeToScreen(message) {if(DEBUG_FLAG){$("#debuggerInfo").val($("#debuggerInfo").val() + "\n" + message);}}function sendMessageBySocket(){var toUserId = $("#userId").val();var msg = $("#msg").val();var data = {"fromUserId": userId,"toUserId": toUserId,"msg": msg};wsObj.send(JSON.stringify(data));}</script>
</head><body style="margin: 0px;padding: 0px;overflow: hidden; ">
<!-- 显示消息-->
<textarea id="debuggerInfo" style="width:100%;height:200px;"></textarea>
<!-- 发送消息-->
<div>用户:<input type="text" id="userId"></input></div>
<div>消息:<input type="text" id="msg"></input></div>
<div><input type="button" value="发送消息" onclick="sendMessageBySocket()"></input></div>
</body>
</html>

四、代码设计与测试

1、失败重连

在客户端和服务端连接失败是进行失败重连,代码如下:

2、心跳检测

服务器:

在客户端和服务器长时间未通信时,客户端会向服务器发一个ping,若服务器没问题则会给客户端返回一个pong的回复,以确保连接正常。

3、用户在线聊天测试

可以看到聊天可以正常进行。

五、案例源码

Websocket案例代码: Websocket案例代码

Websocket 技术实践 实现在线聊天系统相关推荐

  1. 用websocket技术开发的web聊天系统

    在项目中可以web页面聊天,发站内信,语音提箱功能!该套源码能够正常的运行起来! 链接:https://pan.baidu.com/s/12rNJMygmSCdTaP552FF9-w 提取码:bulq ...

  2. 利用websocket实现web端在线客服实时聊天系统

    在线聊天系统 需求场景模拟 开发需求 一.技术选型 二.需求分析 效果演示 软件需求实现 1.技术架构 2.实现流程图:(`仅供参考`) 一.数据库设计 二.代码实现 1.web端 1.前端代码 2. ...

  3. php主动推送弹幕_百万在线的美拍直播弹幕系统的实时推送技术实践之路

    1.内容概述 1.jpg (30.13 KB, 下载次数: 321) 2 年前 上传 直播弹幕是直播系统的核心功能之一.如何迅速作出一个有很好扩展性的弹幕系统?如何应对业务迅速发展?相信很多工程师/架 ...

  4. ​周锦民:腾讯在线教育视频互动直播间技术实践

    本文来自腾讯云技术沙龙,本次沙龙主题为在线教育个性化教学技术实践 演讲嘉宾:周锦民 | 2011年毕业进入腾讯, 现任在线教育部在线教育后台中心高级工程师,多年linux后台开发工作经验,目前主要负责 ...

  5. 实时音视频聊天中超低延迟架构的思考与技术实践

    1.前言 从直播在线上抓娃娃,不断变化的是玩法的创新,始终不变的是对超低延迟的苛求.实时架构是超低延迟的基石,如何在信源编码.信道编码和实时传输整个链条来构建实时架构?在实时架构的基础之上,如果通过优 ...

  6. 基于php和服务器推技术的web即时聊天系统,基于php和服务器推技术的Web即时聊天系统...

    基于php和服务器推技术的Web即时聊天系统① 王振兴, 黄静 [摘要]摘要: 基于http协议应用于Web端, 实现一个浏览器无关的.便于移植的.高性能的Web即时聊天系统. 系统使用服务器推技术中 ...

  7. 【转】WebSocket详解(一):初步认识WebSocket技术

    1.前言 HTML5规范在传统的web交互基础上为我们带来了众多的新特性,随着web技术被广泛用于web APP的开发,这些新特性得以推广和使用,而websocket作为一种新的web通信技术具有巨大 ...

  8. WebSocket详解(一):初步认识WebSocket技术

    WebSocket详解(一):初步认识WebSocket技术 1.前言 HTML5规范在传统的web交互基础上为我们带来了众多的新特性,随着web技术被广泛用于web APP的开发,这些新特性得以推广 ...

  9. IM开发干货分享:网易云信IM客户端的聊天消息全文检索技术实践

    1.引言 在IM客户端的使用场景中,基于本地数据的全文检索功能扮演着重要的角色,最常用的比如:查找聊天记录.联系人,就像下图这样. ▲ 微信的聊天记录查找功能 类似于IM中的聊天记录查找.联系人搜索这 ...

最新文章

  1. 2021年4月12日 阿里供应链Java研发实习面试(一面)(含总结)
  2. 一款功能齐全的网管软件:Ip-tools
  3. _cdecl和_stdcal的区别
  4. 玩转oracle 11g(33):无监听程序
  5. flowable 数据库表结构 梳理
  6. 【Python】nltk库使用报错之punkt安装
  7. 【转】Mac系统中安装homebrew(类似redhat|Centos中的yum;类似Ubuntu中的apt-get)
  8. python分行打印list_python怎么打印list-问答-阿里云开发者社区-阿里云
  9. 《Java遗传算法编程》—— 1.8 参数
  10. 【GNN框架系列】DGL第二讲:使用Deep Graph Library实现GNN进行链接预测
  11. 原来,我一直都不会用Windows
  12. 一些不为人知的秘密[迅雷和快播]
  13. web前端开发技术期末考试_(完整word版)web前端开发技术试卷三
  14. AxureRP8实战手册
  15. 嵌入式设计 | 基于51单片机的tea5767收音机设计实操教程
  16. foxmail邮箱修改服务器,foxmail基本设置方法.foxmail使用技巧
  17. 网站怎么样对接微信公众号,看以下操作
  18. python设置端口控制ie浏览器_[Python爬虫] 之二:Selenium 调用IEDriverServer打开IE浏览器安装配置...
  19. SSD_OneStage
  20. [转]JavaScript和html5 canvas生成圆形印章

热门文章

  1. Office 2003 sp3(CVE-2012-0158)漏洞分析报告
  2. CUDA笔记2-循环展开
  3. 计算机网络统考outlook操作视频,2020年9月网络教育统考《计算机应用基础》Outlook模拟题试卷...
  4. jquery.slides.js 幻灯片脚本使用方法
  5. 下一代机器学习的应走之路
  6. 杭电计算机学院吴迅冬,活动预告 | 叮~ 欢迎收看杭电Running Man
  7. Cesium中笛卡尔坐标系到底是什么鬼
  8. java内省的意思,java内省机制 + 内省是什么 + 内省实现方式 + 和反射的区别
  9. RK3399+XILINX K7 FPGA 应用于雷达通信遥测成像等领域
  10. Linux 学习笔记——二、主机规划与磁盘分区