当前位置: 首页 > news >正文

【后端】websocket学习笔记

文章目录

  • 1. 消息推送常见方式
    • 1.1 轮询 VS 长轮询
    • 1.2 SSE(server-sent event)服务器发送事件
  • 2. websocket介绍
    • 2.1 介绍
    • 2.2 原理
    • 2.3 websoket API
      • 2.3.1 客户端【浏览器】API
      • 2.3.2 服务端API
  • 3. 代码实现
    • 3.1 流程分析
    • 3.2 pom依赖
    • 3.3 配置类
    • 3.4 消息格式
    • 3.5 消息类
  • 4. 前端代码(非视频源码)

参考视频
【后端&网络&大数据&数据库目录贴】

1. 消息推送常见方式

  • 轮询
  • 长轮询
  • websocket
  • SSE

1.1 轮询 VS 长轮询

在这里插入图片描述

1.2 SSE(server-sent event)服务器发送事件

  • SSE在服务器和客户端之间打开一个单向通道
  • 服务端响应的不再是一次性的数据包,而是text/event-stream类型的数据流信息
  • 服务器有数据变更时将数据流式传输到客户端
    在这里插入图片描述

2. websocket介绍

2.1 介绍

websocket是一种基于TCP链接上进行全双工通信的协议

  • 全双工:允许数据在两个方向上同时传输。(TCP是全双工,HTTP是基于TCP的)
  • 半双工:允许数据在两个方向上传输,但是同一个时间段内只允许一个方向上传输。
    在这里插入图片描述

2.2 原理

在这里插入图片描述

  • ws://localhost?chat 依然是http协议
  • Connection:UpgradeUpgrade: websocket表明连接升级
  • 响应码 101说明已经切换成功

2.3 websoket API

2.3.1 客户端【浏览器】API

  • websocket对象创建
let ws=new WebSocket(URL);
  • websocket对象相关事件
    在这里插入图片描述
  • websocket对象提供的方法
    在这里插入图片描述

2.3.2 服务端API

在这里插入图片描述

  • 服务端如何接收客户端发送的数据呢?
    在这里插入图片描述
  • 服务端如何推送数据给客户端呢?
    在这里插入图片描述

3. 代码实现

3.1 流程分析

在这里插入图片描述

3.2 pom依赖

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

3.3 配置类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.4 消息格式

在这里插入图片描述

3.5 消息类

@ServerEndpoint(value = "/chat", configurator = GetHttpSessionConfigurator.class)
@Component
public class ChatEndpoint {public static final Map<String, Session> sessionsMap = new ConcurrentHashMap<>();private HttpSession httpSession;/*** 建立websocket连接后,被调用** @param session*/@OnOpenpublic void onOpen(Session session, EndpointConfig config) {//1.将session进行保存this.httpSession = (HttpSession) config.getUserProperties().get("httpSession");String userName = (String) httpSession.getAttribute("userName");ChatEndpoint.sessionsMap.put(userName, session);//2. 广播消息,需要将登录的所有的用户推送给所有用户String sendMessage = MessageUtil.sendMessage(true, null, userName + "上线");boardcast(sendMessage);}/*** 广播消息*/private void boardcast(String message) {// 遍历 map 集合Set<Map.Entry<String, Session>> entries = ChatEndpoint.sessionsMap.entrySet();for (Map.Entry<String, Session> entry : entries) {Session session = entry.getValue();try {session.getBasicRemote().sendText(message);} catch (IOException e) {// 记录日志}}}@OnMessagepublic void onMessage(String message) {try {String fromName = (String) this.httpSession.getAttribute("userName");// 将消息推送给指定的用户   message : {"toName":"张三","message":"你好"}ClientMessage clientMessage = JSON.parseObject(message, ClientMessage.class);Session session = ChatEndpoint.sessionsMap.get(clientMessage.getToName());String sendMessage = MessageUtil.sendMessage(false, fromName, clientMessage.getMessage());session.getBasicRemote().sendText(sendMessage);} catch (IOException e) {throw new RuntimeException(e);}}/*** 当websocket连接断开时,此方法会被处罚*/@OnClosepublic void onClose(Session session) {
// 从在线用户集合中剔除断开连接的用户String userName = (String) this.httpSession.getAttribute("userName");ChatEndpoint.sessionsMap.remove(userName);// 通知其他用户当前用户下线String sendMessage = MessageUtil.sendMessage(true, null, userName + "上线");boardcast(sendMessage);}
}

4. 前端代码(非视频源码)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="js/jquery.min.js"></script>
</head>
<body>
<p>【fromUserId】:<div><input id="userId" name="userId" type="text" value="10"></div>
<p>【toUserId】:<div><input id="toUserId" name="toUserId" type="text" value="20"></div>
<p>【发送的消息】:<div><input id="contentText" name="contentText" type="text" value="hello websocket"></div>
<p>【收到的内容】:<div><textarea id="receText"></textarea></div><button id="openSocket">开启socket</button><button id="sendMessage">发送消息</button><button id="closeWs">关闭连接</button>
<script>$(function (){console.log('加兹阿勒')const urlParams = new URLSearchParams(window.location.search);console.log(urlParams)var fromUserId = urlParams.get('fromUserId');$('#userId').val(fromUserId)})var ws ;function openSocket() {if(typeof(WebSocket) == "undefined") {console.log("您的浏览器不支持WebSocket");}else{console.log("您的浏览器支持WebSocket");//实现化WebSocket对象,指定要连接的服务器地址与端口  建立连接//等同于socket = new WebSocket("ws://localhost:8888/xxxx/im/25");//var socketUrl="${request.contextPath}/im/"+$("#userId").val();var socketUrl="http://localhost:8081/chat";socketUrl=socketUrl.replace("https","wss").replace("http","ws");console.log(socketUrl);if(ws !=null){ws .close();ws =null;}ws = new WebSocket(socketUrl);// 当 WebSocket 成功建立连接时触发ws.onopen  = function(event) {console.log("WebSocket is connected now.");// 在这里你可以发送一些初始消息到服务器// ws.send("Hello, Server!");};// 当接收到来自服务器的消息时触发ws.onmessage = function(event) {console.log("Received data from server: " + event.data);// 处理从服务器接收到的数据var parse = JSON.parse(event.data);$('#receText').val(parse.message);};// 当 WebSocket 连接关闭时触发ws.onclose = function(event) {if (event.wasClean) {console.log("WebSocket connection closed cleanly, code=" + event.code + " reason=" + event.reason);} else {// 例如,服务器进程被终止而关闭console.log("WebSocket connection died");}};// 当 WebSocket 连接出现错误时触发ws.onerror = function(error) {console.error("WebSocket Error: " + error);};}}function sendMessage() {if(typeof(WebSocket) == "undefined") {console.log("您的浏览器不支持WebSocket");}else {console.log("您的浏览器支持WebSocket");console.log('{"toUserId":"'+$("#toUserId").val()+'","contentText":"'+$("#contentText").val()+'"}');ws.send('{"toName":"'+$("#toUserId").val()+'","message":"'+$("#contentText").val()+'"}');}}function closeWs(){ws.close();}$("#openSocket").on('click', openSocket);$("#sendMessage").on('click',sendMessage);$("#closeWs").on('click', closeWs);
</script>
</body>
</html>

相关文章:

【后端】websocket学习笔记

文章目录 1. 消息推送常见方式1.1 轮询 VS 长轮询1.2 SSE&#xff08;server-sent event)服务器发送事件 2. websocket介绍2.1 介绍2.2 原理2.3 websoket API2.3.1 客户端【浏览器】API2.3.2 服务端API 3. 代码实现3.1 流程分析3.2 pom依赖3.3 配置类3.4 消息格式3.5 消息类 4.…...

DataWhale - 吃瓜教程学习笔记(一)

学习视频&#xff1a;第1章-绪论_哔哩哔哩_bilibili 西瓜书对应章节&#xff1a; 第一章 & 第二章 文章目录 机器学习三观What&#xff1a;什么是机器学习&#xff1f;Why: 为什么要学机器学习&#xff1f;1. 机器学习理论研究2. 机器学习系统开发3. 机器学习算法迁移 &…...

Attention Is All You Need论文地址

论文地址 点击即可...

如何优雅的一键下载OpenHarmony活跃分支代码?请关注【itopen: ohos_download】

itopen组织&#xff1a;1、提供OpenHarmony优雅实用的小工具2、手把手适配riscv qemu linux的三方库移植3、未来计划riscv qemu ohos的三方库移植 小程序开发4、一切拥抱开源&#xff0c;拥抱国产化 一、概述 为方便大家每次下载OpenHarmony不同分支/tag代码&#xff0c…...

torch.topk用法

torch.topk用法 介绍使用示例 介绍 官网介绍&#xff1a;https://pytorch.org/docs/stable/generated/torch.topk.html 在指定维度选取k个最大&#xff08;最小&#xff09;的值。 使用示例 values torch.tensor([[2, 1, 3], [1, 2, 3]]) # values # tensor([[2, 1, 3], #…...

终极版本的Typora上传到博客园和csdn

激活插件 下载网址是这个&#xff1a; https://codeload.github.com/obgnail/typora_plugin/zip/refs/tags/1.9.4 解压之后这样的&#xff1a; 解压之后将plugin&#xff0c;复制到自己的安装目录下的resources 点击安装即可&#xff1a; 更改配置文件 "dependencies&q…...

洛谷:P5707【深基2.例12】上学迟到

1. 题目链接 https://www.luogu.com.cn/problem/P5707 【深基2.例12】上学迟到 2. 题目描述 学校和y的家距离s米&#xff0c;s以v的速度去学校&#xff0c;8点之前到&#xff0c;y出门前要打扫10分钟卫生&#xff0c;求s最晚的出门时间 输入&#xff1a;两个正整数路程s&…...

数据治理:数据提取过程中的合规性与安全性

数据治理&#xff1a;数据提取过程中的合规性与安全性 随着数字化时代的到来&#xff0c;数据已经成为企业运营和决策的核心驱动力。然而&#xff0c;在数据提取的过程中&#xff0c;确保数据的合规性和安全性成为了企业面临的重要挑战。数据治理作为一种系统的方法&#xff0…...

24计算机应届生的活路是什么

不够大胆❗ 很多小伙伴在找工作时觉得自己没有竞争力&#xff0c;很没有自信&#xff0c;以至于很害怕找工作面试&#xff0c;被人否定的感觉很不好受。 其实很多工作并没有想象中的高大上&#xff0c;不要害怕&#xff0c;计算机就业的方向是真的广&#xff0c;不要走窄了&…...

HTML页面布局-使用div示例

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body><!--text-align:center 文字水平居中line-height&#xff1a;200px; 文字垂直居中,行高设置跟高…...

怎么把webp文件转换为jpg?快来试试这四种转换方法!

怎么把webp文件转换为jpg&#xff1f;Webp是一种不常见的图片格式&#xff0c;这种格式在使用过程中有很多缺点&#xff0c;首先它的浏览器兼容性不是很强&#xff0c;这就代表大家无法随意进行网络传输&#xff0c;可能需要准备特定的操作才能进行&#xff0c;然后编辑webp的工…...

计算机网络(7) 错误检测

一.校验和 使用补码计算校验和是一种常见的错误检测方法&#xff0c;应用于网络协议如IP和TCP。补码是二进制数的一种表示方法&#xff0c;可以有效地处理符号位和进位。下面是如何利用补码计算校验和的详细步骤和算数例子。 ### 计算步骤 1. **将数据分块**&#xff1a;将数…...

实体类status属性使用枚举类型的步骤

1. 问题引出 当实体类的状态属性为Integer类型时&#xff0c;容易写错 2. 初步修改 把状态属性强制为某个类型&#xff0c;并且自定义一些可供选择的常量。 public class LessonStatus {public static final LessonStatus NOT_LEARNED new LessonStatus(0,"未学习"…...

pytorch基础【4】梯度计算、链式法则、梯度清零

文章目录 梯度计算计算图&#xff08;Computational Graph&#xff09;梯度求导&#xff08;Gradient Computation&#xff09;函数与概念 示例代码更多细节梯度求导的过程梯度求导的基本步骤示例代码注意事项总结 链式法则是什么&#xff1f;链式法则的数学定义链式法则在深度…...

mapreduce综合应用案例 — 招聘数据清洗

MapReduce是一个编程模型和处理大数据集的框架&#xff0c;它由Google开发并广泛使用于分布式计算环境中。MapReduce模型包含两个主要的函数&#xff1a;Map和Reduce。Map函数用于处理输入的键值对生成中间键值对&#xff0c;Reduce函数则用于合并Map函数输出的具有相同键的中间…...

发力采销,京东的“用户关系学”

作者 | 曾响铃 文 | 响铃说 40多岁打扮精致的城市女性&#xff0c;在西藏那曲的偏远农村&#xff0c;坐着藏民的摩托车&#xff0c;行驶在悬崖边的烂泥路上&#xff0c;只因为受顾客的“委托”&#xff0c;要寻找最原生态的藏区某款产品。 30多岁的憨厚中年男性&#xff0c;…...

期望23K,go高级社招面试复盘

面经哥只做互联网社招面试经历分享&#xff0c;关注我&#xff0c;每日推送精选面经&#xff0c;面试前&#xff0c;先找面经哥 我最终还是上岸了&#xff0c;花了一周总结了3万字的go社招高级面试知识体系思维导图&#xff0c;分享出来希望能帮助有缘人吧&#xff0c;以下只是…...

电感(线圈)具有哪些基本特性

首先&#xff0c;电感&#xff08;线圈&#xff09;具有以下基本特性&#xff0c;称之为“电感的感性电抗” ?①直流基本上直接流过。 ?②对于交流&#xff0c;起到类似电阻的作用。 ?③频率越高越难通过。 下面是表示电感的频率和阻抗特性的示意图。 在理想电感器中&#…...

tkinter实现一个GUI界面-快速入手

目录 一个简单界面输出效果其他功能插入进度条文本框内容输入和删除标签内容显示和删除 一个简单界面 含插入文本、文本框、按钮、按钮调用函数 # -*- coding: UTF-8 -*-import tkinter as tk from tkinter import END from tkinter import filedialog from tkinter impor…...

Top10在线音频剪辑软件,你了解几款?(免费分享)

多年来&#xff0c;随着音乐制作人和音频工程师的需求不断增长&#xff0c;音频剪辑软件领域经历了巨大的发展。最新的音频剪辑软件提供了从基本录制到最终发布所需的一切功能。其中一些软件专为播客设计&#xff0c;一些软件是免费的&#xff0c;并且一些软件提供了出色的音效…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

快刀集(1): 一刀斩断视频片头广告

一刀流&#xff1a;用一个简单脚本&#xff0c;秒杀视频片头广告&#xff0c;还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农&#xff0c;平时写代码之余看看电影、补补片&#xff0c;是再正常不过的事。 电影嘛&#xff0c;要沉浸&#xff0c;…...

前端中slice和splic的区别

1. slice slice 用于从数组中提取一部分元素&#xff0c;返回一个新的数组。 特点&#xff1a; 不修改原数组&#xff1a;slice 不会改变原数组&#xff0c;而是返回一个新的数组。提取数组的部分&#xff1a;slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...

绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化

iOS 应用的发布流程一直是开发链路中最“苹果味”的环节&#xff1a;强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说&#xff0c;这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发&#xff08;例如 Flutter、React Na…...