websoket 学习笔记
目录
基本概念
工作原理
优势
应用场景
HTTP协议与 webSoket协议之间的对比
消息推送场景
1. 轮询(Polling)
2. 长轮询(Long Polling)
3. 服务器发送事件(Server-Sent Events, SSE)
4. WebSocket
服务端WebSoket
基本介绍
引入依赖
核心API示例
聊天消息demo流程分析
配置类
webSocketConfig(注入ServerEndpoint注解)
GetHttpSessionConfig(存储Session会话对象)
服务类
Server端Socket
客户端
WebSocket 是一种基于 TCP 的网络通信协议,允许在客户端和服务器之间建立持久的双向通信连接。
基本概念
-
全双工通信(Full Duplex):WebSocket 支持客户端和服务器在同一连接上同时发送和接收数据,允许数据在两个方向上同时传输。
-
半双工(Half Duplex):允许数据在两个方向上传输,但是同一个时间段内只允许一个方向上传输。
-
持久连接:通过一次握手建立连接后,连接会一直保持,无需每次通信都重新建立
-
低延迟与高效性:减少了传统 HTTP 请求-响应模式中的频繁连接开销,数据传输更高效
工作原理
-
握手阶段:客户端通过 HTTP 请求向服务器发起 WebSocket 升级请求,服务器响应后将连接升级为 WebSocket
-
数据传输:连接建立后,数据以帧的形式在客户端和服务器之间传输
-
关闭连接:当一方关闭连接时,WebSocket 会发送关闭帧,通知对方关闭连接

优势
-
实时性:适合需要快速响应和更新的场景
-
节省资源:减少了不必要的网络请求和响应,降低了带宽和服务器资源消耗
-
跨平台支持:主流浏览器和服务器端语言均支持 WebSocket
应用场景
-
实时通信:如在线聊天、实时游戏
-
数据推送:服务器主动向客户端推送数据,如股票行情、天气预报
-
实时监控:如视频监控、设备状态监控
WebSocket 是现代 Web 开发中实现高效实时通信的重要技术,广泛应用于各种需要快速数据交互的场景。
HTTP协议与 webSoket协议之间的对比

用到最多的其中一个场景就是 消息推送。
消息推送场景
消息推送是指服务器主动向客户端发送信息的技术。以下是几种常见的消息推送方式:
1. 轮询(Polling)
-
原理:客户端每隔固定时间向服务器发送请求,查询是否有新消息。
-
优点:
-
实现简单,兼容性好,不需要额外的服务器支持。
-
-
缺点:
-
频繁请求会增加服务器负担,浪费带宽。
-
实时性较差,消息延迟取决于轮询间隔。
-
-
适用场景:对实时性要求不高的场景,如邮件通知。
2. 长轮询(Long Polling)
-
原理:客户端向服务器发送请求,服务器保持连接打开,直到有新消息才返回响应。
-
优点:
-
减少了无效请求,相比普通轮询更节省资源。
-
实时性更好。
-
-
缺点:
-
服务器需要保持大量连接,对服务器资源要求较高。
-
如果消息间隔过长,可能导致连接超时。
-
-
适用场景:对实时性有一定要求但不希望使用复杂技术的场景。

3. 服务器发送事件(Server-Sent Events, SSE)
原理:
-
服务器通过 HTTP 连接向客户端推送数据,客户端通过
EventSource接收消息。 -
SSE在服务器和客户端之间打开一个单向通道
-
服务端响应的不再是一次性的数据包,而是text/event-stream类型的数据流信息
-
服务器有数据变更时将数据流式传输到客户端
优点:
-
实现简单,基于 HTTP,兼容性较好。
-
只支持单向通信(服务器到客户端),适合通知类应用。
缺点:
-
不支持双向通信。
-
不支持跨域,需要服务器和客户端在同一个域下。
适用场景:股票行情、新闻推送等单向通知场景。

4. WebSocket
-
原理:通过一次握手建立持久的双向通信连接,客户端和服务器可以随时发送和接收消息。
-
优点:
-
全双工通信,实时性高。
-
数据传输效率高,减少了 HTTP 请求的开销。
-
-
缺点:
-
实现复杂,需要服务器和客户端都支持 WebSocket 协议。
-
需要额外处理连接的建立和关闭。
-
-
适用场景:在线聊天、实时游戏、实时协作工具等。
不同消息推送方式各有优缺点,选择时需要根据具体需求和场景进行权衡。例如:
-
如果对实时性要求不高,可以选择轮询或长轮询。
-
如果需要高效实时的双向通信,WebSocket 是更好的选择。
服务端WebSoket
基本介绍


引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
核心API示例

聊天消息demo流程分析

配置类
webSocketConfig(注入ServerEndpoint注解)
package com.angindem.server.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {@Bean
// 注入ServerEndpointExporter,自动注册使用@ServerEndpoint注解的public ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}
GetHttpSessionConfig(存储Session会话对象)
package com.angindem.server.config;import com.angindem.common.utils.CommonUtils;
import com.angindem.common.utils.IpUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import jakarta.websocket.HandshakeResponse;
import jakarta.websocket.server.HandshakeRequest;
import jakarta.websocket.server.ServerEndpointConfig;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;public class GetHttpSessionConfig extends ServerEndpointConfig.Configurator {@Overridepublic void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
// 获取 HttpSession 对象HttpSession httpSession = (HttpSession) request.getHttpSession();// 获取当前请求的HttpServletRequestServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest req = attributes.getRequest();if (httpSession == null) httpSession = req.getSession();String ip = IpUtils.getIpAddress(req);httpSession.setAttribute("user", CommonUtils.getRandomString(8));// 将 HttpSession 对象存储到 ServerEndpointConfig 中sec.getUserProperties().put(HttpSession.class.getName(), httpSession);// 将HttpServletRequest存储到EndpointConfig的用户属性中sec.getUserProperties().put(String.class.getName(), ip);}
}
服务类
Server端Socket
package com.angindem.server.wx;
import com.alibaba.fastjson2.JSON;
import com.angindem.common.utils.MessageUtils;
import com.angindem.server.config.GetHttpSessionConfig;
import com.angindem.server.wx.pojo.Message;
import jakarta.servlet.http.HttpSession;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@Component
@ServerEndpoint(value = "/chat", configurator = GetHttpSessionConfig.class)
public class ChatEndPoint {// ConcurrentHashMap 高并发的多线程访问的哈希Mappublic static final Map<String, Session> onlineUsers = new ConcurrentHashMap<>();private HttpSession httpSession;@OnOpenpublic void onOpen(Session session, EndpointConfig config) {log.info("连接建立成功");
// 1、将 Session 放入到集合中,方便后续使用this.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());String reqIp = (String) config.getUserProperties().get(String.class.getName());String user = MessageUtils.getNowSessionUserName(this.httpSession);onlineUsers.put(user, session);
// 2、广播消息。需要将登录的所有用户推送给所有用户log.info("当前在线人数:{}", onlineUsers.size());log.info("当前用户:{},来自:{}", user, reqIp);String message = MessageUtils.getDataMessage("system", user, MessageUtils.getFrinds());MessageUtils.broadcastAllUsers(message);}@OnMessagepublic void onMessage(String message) {log.info("收到消息:{}", message);Message msg = JSON.parseObject(message, Message.class);// 获取 消息接收方的用户名String toName = msg.getToName();String mess = msg.getMessage();String user = MessageUtils.getNowSessionUserName(this.httpSession);String sendMessage = MessageUtils.getMessage("user", user, mess);// 获取消息接收方用户对象的 session 对象
// Session session = onlineUsers.get(toName);
// session.getBasicRemote().sendText(sendMessage);MessageUtils.broadcastAllUsers(sendMessage);}@OnClosepublic void onClose(Session session) {log.info("连接关闭");
// 1、从 onlineUsers 中剔除当前的 session 对象String user = MessageUtils.getNowSessionUserName(this.httpSession);onlineUsers.remove(user);
// 2、通知其它所有的用户,当前用户已经下线log.info("当前在线人数:{}", onlineUsers.size());String message = MessageUtils.getDataMessage("system", user, MessageUtils.getFrinds());MessageUtils.broadcastAllUsers(message);}
}
客户端
(VueUse的 webSocket 客户端)
/*** status 是连接的状态值* data 是 socket 推送过来的消息* send 是一个方法, 用来发送消息给后台* close 是一个方法,关闭 socket 连接* open 如果当前的websocket是活跃的,将会关闭它重新打开一个新的*/
const { status, data, close, open, send } = useWebSocket(`ws://localhost:9898/chat`, {onConnected: function (ws) {console.log('websocket 连接成功!', ws)},onDisconnected: function (ws, event) {console.log('onDisconnected')},onError: function (ws, event) {console.log('onError', event)},onMessage: function (ws, event) {console.log('event.data', event.data)if (event.data) {// messageInfo.value = []const info = JSON.parse(event.data)console.log(info) // 这里就是websocket每次发送的消息if (info.data) updateUsers(info.data);if (info.message) messageInfo.value.push(info)}},heartbeat: false,autoClose: false, // 自动关闭连接});
扩展:
同时可以通过 vue 中的 watch 监听发送过来的数据
import { watch } from 'vue';
//获取数据时必须要监视,此处的data就是上面结构出的data
watch(data, () => {//获取到的数据为data.valueconsole.log(data.value)
})
发送消息到服务端
//需要发送给服务器的数据
const info = "你好吗?"//send方法,此处的send为上面解构出的send
send(info)
相关文章:
websoket 学习笔记
目录 基本概念 工作原理 优势 应用场景 HTTP协议与 webSoket协议之间的对比 消息推送场景 1. 轮询(Polling) 2. 长轮询(Long Polling) 3. 服务器发送事件(Server-Sent Events, SSE) 4. WebSocket…...
博途 TIA Portal之1200做从站与汇川EASY的TCP通讯
上篇我们写到了博途做主站与汇川EASY的通讯。通讯操作起来很简单,当然所谓的简单,也是相对的,如果操作成功一次,那么后面就很容易了, 如果操作不成功,就会很遭心。本篇我们将1200做从站,与汇川EASY做主站进行TCP的通讯。 1、硬件准备 1200PLC一台,带调试助手的PC机一…...
【数据结构_6下篇】有关链表的oj题
思路: 1.分别求出这两个链表的长度 2.创建两个引用,指向两个链表的头节点;找到长度长的链表,让她的引用先走差值步数 3.让这两个引用,同时往后走,每个循环各自走一步 然后再判定两个引用是否指向同一个…...
vscode+wsl 运行编译 c++
linux 的 windows 子系统(wsl)是 windows 的一项功能,可以安装 Linux 的发行版,例如(Ubuntu,Kali,Arch Linux)等,从而可以直接在 windows 下使用 Linux 应用程序…...
快速幂(蓝桥杯)
1. 递归实现 递归方法通过将问题分解为更小的子问题来实现。具体步骤如下: 如果指数 b 为 0,返回 1。 如果 b 是偶数,则递归计算 (a^2)b/2。 如果 b 是奇数,则递归计算 a⋅(a^2)(b−1)/2。 伪代码: function fas…...
狂神SQL学习笔记一:初识MySQL、关系型数据库和非关系型数据库
菜鸟教程学习一半了,但是已经疲倦了,所以换一个课程学习,来提升学习质量,可能会有很多已经学习到的地方,就当是复习巩固了。 按照SQL学习课程来划分,分为45集,所以可能也会写45篇文章ÿ…...
关于 Spring Boot 微服务解决方案的对比,并以 Spring Cloud Alibaba 为例,详细说明其核心组件的使用方式、配置及代码示例
以下是关于 Spring Boot 微服务解决方案的对比,并以 Spring Cloud Alibaba 为例,详细说明其核心组件的使用方式、配置及代码示例: 关于 Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案! https://sca.aliyun.com/?spm7145af80…...
VS 基于git工程编译版本自动添加版本号
目录 概要 实现方案 概要 最近在用visual Studio 开发MFC项目时,需要在release版本编译后的exe文件自动追加版本信息。 由于我们用的git工程管理,即需要基于最新的git 提交来打版本。 比如: MFCApplication_V1.0.2_9.exe 由于git 提交信…...
小程序开发指南
小程序开发指南 目录 1. 小程序开发概述 1.1 什么是小程序1.2 小程序的优势1.3 小程序的发展历程 2. 开发准备工作 2.1 选择开发平台2.2 开发环境搭建2.3 开发模式选择 3. 小程序开发流程 3.1 项目规划3.2 界面设计3.3 代码开发3.4 基本开发示例3.5 数据存储3.6 网络请求3.7 …...
MySQL 超详细安装教程与常见问题解决方案
一、MySQL 安装教程 1. Windows 系统安装(以 MySQL 8.0 为例) 步骤 1:下载 MySQL Installer 访问 MySQL 官网下载页面。 选择 Windows (x86, 64-bit), MSI Installer(推荐使用完整版 mysql-installer-web-community-8.0.xx.xx.…...
pytorch软件封装
封装代码,通过传入文件名,即可输出类别信息 上一章节,我们做了关于动物图像的分类,接下来我们把程序封装,然后进行预测。 单张图片的predict文件 predict.py 按着路径,导入单张图片做预测from torchvis…...
【多线程-第四天-自己模拟SDWebImage的下载图片功能-看SDWebImage的Demo Objective-C语言】
一、我们打开之前我们写的异步下载网络图片的项目,把刚刚我们写好的分类拖进来 1.我们这个分类包含哪些文件: 1)HMDownloaderOperation类, 2)HMDownloaderOperationManager类, 3)NSString+Sandbox分类, 4)UIImageView+WebCache分类, 这四个文件吧,把它们拖过来…...
电脑提示“找不到mfc140u.dll“的完整解决方案:从原因分析到彻底修复
当你启动某个软件或游戏时,突然遭遇"无法启动程序,因为计算机中丢失mfc140u.dll"的错误提示,这确实令人沮丧。mfc140u.dll是Microsoft Foundation Classes(MFC)库的重要组成部分,属于Visual C Re…...
图像变换方式区别对比(Opencv)
1. 变换示例 import cv2 import matplotlib.pyplot as plotimg cv2.imread(url) img_cut img[100:200, 200:300] img_rsize cv2.resize(img, (50, 50)) (hight,width) img.shape[:2] rotate_matrix cv2.getRotationMatrix2D((hight//2, width//2), 50, 1) img_wa cv2.wa…...
图像颜色空间对比(Opencv)
1. 颜色转换 import cv2 import matplotlib.pyplot as plotimg cv2.imread("tmp.jpg") img_r cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img_g cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) img_h cv2.cvtColor(img, cv2.COLOR_BGR2HSV) img_l cv2.cvtColor(img, cv2.C…...
【NLP】24. spaCy 教程:自然语言处理核心操作指南(进阶)
spaCy 中文教程:自然语言处理核心操作指南(进阶) 1. 识别文本中带有“百分号”的数字 import spacy# 创建一个空的英文语言模型 nlp spacy.blank("en")# 处理输入文本 doc nlp("In 1990, more than 60% of people in East…...
每天学一个 Linux 命令(15):man
可访问网站查看,视觉品味拉满:http://www.616vip.cn/15/index.html 每天学一个 Linux 命令(15):man 命令简介 man(Manual)是 Linux 中最核心的命令之一,用于查看命令、系统调用、库函数等的手册文档。它是用户和开发者获取帮助的核心工具,几乎覆盖了系统中的所有功…...
必刷算法100题之计算右侧小于当前元素的个数
题目链接 315. 计算右侧小于当前元素的个数 - 力扣(LeetCode) 题目解析 计算数组里面所有元素右侧比它小的数的个数, 并且组成一个数组,进行返回 算法原理 归并解法(分治) 当前元素的后面, 有多少个比我小(降序) 我们要找到第一比左边小的元素, 这样…...
Python依赖注入完全指南:高效解耦、技术深析与实践落地
Python依赖注入完全指南:高效解耦、技术深析与实践落地 摘要 依赖注入(DI)不仅是一种设计技术,更是一种解耦的艺术。它通过削减模块间的强耦合性,为系统提供了更高的灵活性和可测试性,特别是在 FastAPI 等…...
android弱网环境数据丢失解决方案(3万字长文)
在移动互联网时代,Android 应用已经成为人们日常生活中不可或缺的一部分。从社交媒体到在线购物,从移动办公到娱乐游戏,用户对应用的依赖程度与日俱增。然而,尽管网络基础设施在全球范围内得到了显著改善,弱网环境依然是一个普遍存在且难以完全避免的现实。特别是在一些发…...
答案之书和源代码
答案之书是一个神秘而神奇的工具,它可以帮助你在遇到问题或犹豫不决的时候找到答案或暗示。这个程序模拟了答案之书的功能,让你随机生成一个简短而有启发性的答案,让你在困境中找到一丝希望。 在这个程序中,你会看到一个画布上显…...
Spring Cloud主要组件介绍
一、Spring Cloud 1、Spring Cloud技术概览 分为:服务治理,链路追踪,消息组件,配置中心,安全控制,分布式任务管理、调度,Cluster工具,Spring Cloud CLI,测试 2、注册中心:常用注册中心(Euerka[AP]、Zookeeper[CP]) 1)Euerka Client(服务提供者)=》注册=》Eue…...
深度学习ResNet模型提取影响特征
大家好,我是带我去滑雪! 影像组学作为近年来医学影像分析领域的重要研究方向,致力于通过从医学图像中高通量提取大量定量特征,以辅助疾病诊断、分型、预后评估及治疗反应预测。这些影像特征涵盖了形状、纹理、灰度统计及波形变换等…...
【Qt】Qt Creator开发基础:项目创建、界面解析与核心概念入门
🍑个人主页:Jupiter. 🚀 所属专栏:QT 欢迎大家点赞收藏评论😊 目录 Qt Creator 新建项⽬认识 Qt Creator 界⾯项⽬⽂件解析Qt 编程注意事项认识对象模型(对象树)Qt 窗⼝坐标体系 Qt Creator 新…...
SimpleITK (sitk) 中查看 DICOM 文件的像素位深(8位或16位)
在 SimpleITK (sitk) 中查看 DICOM 文件的像素位深(8位或16位),可以通过以下方法实现: 方法一:通过 图像像素数组的数据类型 判断 读取 DICOM 文件: 使用 sitk.ReadImage() 加载文件,生成图像对…...
Unity IL2CPP内存泄漏追踪方案(基于Memory Profiler)技术详解
一、IL2CPP内存管理特性与泄漏根源 1. IL2CPP内存架构特点 内存区域管理方式常见泄漏类型托管堆(Managed)GC自动回收静态引用/事件订阅未取消原生堆(Native)手动管理非托管资源未释放桥接层GCHandle/PInvoke跨语言引用未正确释放 对惹,这里有一个游戏开发交流小组…...
制造业项目管理如何做才能更高效?制造企业如何选择适配的数字化项目管理系统工具?
一、制造企业项目管理过程中面临的痛点有哪些? 制造企业在项目管理过程中面临的痛点通常涉及跨部门协作、资源调配、数据整合、风险控制等多个维度,且与行业特性(如离散制造vs流程制造)紧密相关。 进度失控多项目资源冲突信息孤…...
Python批量处理PDF图片详解(插入、压缩、提取、替换、分页、旋转、删除)
目录 一、概述 二、 使用工具 三、Python 在 PDF 中插入图片 3.1 插入图片到现有PDF 3.2 插入图片到新建PDF 3.3 批量插入多张图片到PDF 四、Python 提取 PDF 图片及其元数据 五、Python 替换 PDF 图片 5.1 使用图片替换图片 5.2 使用文字替换图片 六、Python 实现 …...
让 Python 脚本在后台持续运行:架构级解决方案与工业级实践指南
让 Python 脚本在后台持续运行:架构级解决方案与工业级实践指南 一、生产环境需求全景分析 1.1 后台进程的工业级要求矩阵 维度开发环境要求生产环境要求容灾要求可靠性单点运行集群部署跨机房容灾可观测性控制台输出集中式日志分布式追踪资源管理无限制CPU/Memo…...
【后端开发】Spring配置文件
文章目录 配置文件properties配置文件基本语法读取配置文件 yml配置文件基本语法读取配置文件配置空字符串及null单双引号配置对象配置集合配置Map 优缺点优点缺点 配置文件 硬编码是将数据直接嵌入到程序或其他可执行对象的源代码中,也就是常说的"代码写死&q…...
