Websocket (帧格式, 握手过程, Spring 中使用 WebScoket 协议)

什么是 WebSocket

客户端 A 和客户端 B 的消息传播需要借助服务器的中转 (原因是内网不能给另一个局域网的内网直接联通, 需要借助服务器的外网做 “中介”) (NAT 地址转换)

Http 协议 不支持实时通讯 (或者说不支持服务器主动推送数据给客户端)
TCP 本身是具有服务器推送数据这样的功能的, 但是 Http 把它搞丢了 (发明 Http 的大佬们当年所处的时候, 网页就是用来看看新闻, 也没想到后辈能把网页玩出花来)
于是有了 WebSocket 协议.(基于传输层的 TCP 实现) (和 Http 一样, 都是 应用层协议 )

Tomcat 和 Spring 都提供了 WebSocket API, 方便我们通过 WebSocket 协议实现服务器消息推送


Socket 和 WebSocket

Socket 是 OS (或者说传输层) 提供的一组用于网络编程的 API
WebSocket 是一个应用层协议

二者牛马不相及 (没关系)
硬要说有关系, 那就是 WebSocket 的内部实现用到了 Socket


帧格式 (Base Framing Protocol)

在这里插入图片描述

FIN : 表示本帧是否是消息的最后一帧, 是1否0
opcode : 解释 payload data 的类型
MASK : 表示 Payload data 是否经过掩码处理
Payload len: 有效载荷长度 ( [0, 125] – 只使用 Payload len空间, [126] – 表示使用 Payload len 和 Extension Payload len 空间, >[127, …] – 使用 Payload len 和 Extension Payload len 和 Extension payLoad len continue 空间) (即不同数值用不同空间来表示载荷的长度)
masking-key : 掩码内容, 当 MASK = 1 时被启用
payload data : 载荷的具体内容


WebSocket 握手过程

在这里插入图片描述

握手之前, 客户端和浏览器同为 Http 协议
握手开始, 客户端向服务器发起 Http 请求, 根据请求头里包含的信息, 请求服务器进行协议切换
( Connection: upgrade – 能不能换个协议啊)
( Upgrade: WebSocket – 换成 WebSocket 协议行不行啊)
服务器收到浏览器的请求, 并返回响应, 并切换协议格式
( Connection: upgrade – 能换协议啊)
( Upgrade: WebSocket – 换成 WebSocket 协议 ok 啊)
返回的协议内, 状态码为 101, 明确告诉客户端, 我已经切换协议了, 我们之后用 WebSocket 协议进行通信


WebSocket 和 Http 协议是什么关系?

没关系
Http 就是 工具人
客户端和服务器之间通过 Http 协议建立连接, 连接建立完成之后, 就再也用不到 Http 协议了


WebSocket 在 Spring 中的使用

前端

// 创建 websocket 实例, 或者说进行与服务器建立 WebSocket 连接
// let websocket = new WebSocket("ws://127.0.0.1:8080/WebSocketMessage"); // 操作本地
// let websocket = new WebSocket("ws://152.136.56.110:9090/WebSocketMessage"); //操作远程服务器
let websocket = new WebSocket("ws://" + location.host + "/WebSocketMessage"); //统一格式websocket.onopen = function() {// 该方法在连接建立完成后, 被自动调用console.log("websocket 连接成功!");
}websocket.onmessage = function(e) {// 该方法在收到消息时, 被自动调用console.log("websocket 收到消息! " + e.data);// 处理消息响应handleMessage(e.data);	
}websocket.onclose = function() {// 该方法在连接关闭后, 被自动调用console.log("websocket 连接关闭!");
}websocket.onerror = function() {// 该方法在连接异常时, 被自动调用console.log("websocket 连接异常!");
}

后端

导入依赖

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

首先是 创建 Handler 对象, 让其 继承 TextWebSocketHandler
然后将 Handler 注册到 实现 WebSocketConfigurer 接口 的 注册类中

对于 Handler 对象, 有四个常用的方法
afterConnectionEstablished : 该方法在 WebSocket 连接建立 之后, 被自动调用
handlerTextMessage : 该方法在 WebSocket 收到消息 的时候, 被自动调用
handlerTransportError : 该方法在连接 出现异常 的时候, 被自动调用
afterConnectionClosed : 该方法在连接 正常关闭 后, 被自动调用

@Component
public class TestWebSocketAPI extends TextWebSocketHandler {@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {// 该方法会在 websocket 连接建立之后, 被自动调用System.out.println("Test 连接成功!");}@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {// 该方法会在 websocket 收到消息的时候, 被自动调用System.out.println("Test 收到消息!" + message.toString());// 这里可以直接用, 是因为在注册器中, 已经把 HttpSession 中的内容给放到 WebSocketSession 中了User user = session.getAttribute().get("user");// session 是个会话, 里面记录通信双方的信息 (session 中持有 websocket 的通信连接)session.sendMessage(message);}@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {// 这个方法实在 连接出现异常的时候, 被自动调用System.out.println("Test 连接异常!");}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {// 这个方法是在连接正常关闭后, 会被自动调用System.out.println("Test 连接关闭!");}
}

对于注册器, 通过 registerWebSocketHandlers 方法的来注册 Handler (记得给注册器添加注解: @EnableWebSocket)

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Autowiredprivate TestWebSocketAPI testWebSocketAPI;@Autowiredprivate WebSocketAPI webSocketAPI;@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {// 通过本方法, 将创建好的 Handler 类给注册到具体路径上.// 此时浏览器可通过 请求路径, 调用到绑定的 Handler 类.registry.addHandler(testWebSocketAPI, "/test")// 通过注册这个特定的 HttpSession 拦截器, 可以把用户在// HttpSession 中添加的 Attribute 键值对// 往 WebSocketSession 中添加一份.addInterceptors(new HttpSessionHandshakeInterceptor());}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/818557.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【verilog】 reg与寄存器的关系

一、前言 在Verilog中经常用reg定义具有数据寄存功能的单元&#xff0c;但在verilog的使用中&#xff0c;并不代表其一定就是寄存单元&#xff0c;reg还能进行组合逻辑描述&#xff0c;并且在一些场景下&#xff0c;只能使用reg来申明变量。 二、reg型变量生成组合逻辑 在Ve…

linux shell脚本编写(2)

Shell: 命令转换器&#xff0c;高级语言转换成二进制语言。是Linux的一个外壳&#xff0c;它包在Lniux内核的外面&#xff0c;用户和内核之间的交互提供了一个接口。 内置命令&#xff1a;在shell内部不需要shell编辑 外置命令&#xff1a;高级语言要用shell转换成二进制语言 …

(一)Jetpack Compose 从入门到会写

基本概念 Compose 名称由来 众所周知&#xff0c;继承在功能拓展上表现的很脆弱&#xff0c;容易类、函数爆炸&#xff0c;通过代理和包装进行组合会更健壮。 Compose 意为组合&#xff0c;使用上也是把 Compose 函数以 模拟函数调用层级关系的方式 组合到一起&#xff0c;最终…

PCL中VTK场景添加坐标系轴显示

引言 世上本没有坐标系&#xff0c;用的人多了&#xff0c;便定义了坐标系统用来定位。地理坐标系统用于定位地球上的位置&#xff0c;PCL点云库可视化窗口中的坐标系统用于定位其三维世界中的位置。本人刚开始接触学习PCL点云库&#xff0c;计算机图形学基础为零&#xff0c;…

基于Python的卷积网络的车牌识别系统,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

leetcode不同路径

. - 力扣&#xff08;LeetCode&#xff09; 62. 不同路径 中等 相关标签 相关企业 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下…

04_UART串口发送数据

1.配置芯片&#xff0c;如果PA9,PA10的UART引脚被占用&#xff0c;会自动进行重映射 2.代码 int main(void) {uint8_t temp[]"test";/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*…

Unity Shader 流光 边缘光

前言 Unity2021.3.23 一、实现原理 Time控制UV的变化,再采样一张流光贴图.即可实现流光效果。 二、效果及源码展示 1.流光效果 效果描述: 1.边缘光(菲尼尔), 2.从上到下扫描光. 效果图如下: 代码如下: Shader "Unlit/ScanCode" {Properties{_MainTex ("T…

JavaEE企业开发新技术5

目录 2.18 综合应用-1 2.19 综合应用-2 2.20 综合应用-3 2.21 综合应用-4 2.22 综合应用-5 Synchronized &#xff1a; 2.18 综合应用-1 反射的高级应用 DAO开发中&#xff0c;实体类对应DAO的实现类中有很多方法的代码具有高度相似性&#xff0c;为了提供代码的复用性,降低…

MoneyPrinterTurbo-利用AI大模型,一键生成高清短视频

MoneyPrinterTurbo-利用AI大模型&#xff0c;一键生成高清短视频 在今天的信息爆炸的时代&#xff0c;短视频已经成为最受欢迎的信息传递方式之一。无论是分享生活瞬间&#xff0c;还是传递重要信息&#xff0c;短视频都是最直观&#xff0c;最具影响力的手段。但是&#xff0…

微软 SDL 安全研发生命周期详解

微软SDL&#xff08;Security Development Lifecycle&#xff09;是一种安全软件开发的方法论&#xff0c;它强调在整个产品开发过程中融入安全考虑因素。SDL 是一个动态的过程&#xff0c;包括多个阶段和活动&#xff0c;以确保产品的安全开发、测试、部署和运行。Microsoft 要…

11.哀家要长脑子了!

目录 1.453. 最小操作次数使数组元素相等 - 力扣&#xff08;LeetCode&#xff09; 2.665. 非递减数列 - 力扣&#xff08;LeetCode&#xff09; 3. 283. 移动零 - 力扣&#xff08;LeetCode&#xff09; 4. 3114. 替换字符可以得到的最晚时间 - 力扣&#xff08;LeetCode…

说说我理解的数据库中的Schema吧

一、SQL标准对schema如何定义&#xff1f; ISO/IEC 9075-1 SQL标准中将schema定义为描述符的持久命名集合&#xff08;a persistent, named collection of descriptors&#xff09;。 大部分的网上资料定义Schema如下&#xff1a; schema是用来组织和管理数据的一种方式。它…

对中小企业来说,一次的勒索事件有可能造成致命的伤害

勒索攻击越来越频繁 去年的勒索事件数据呈现出显著的增长趋势。具体来说&#xff0c;全球范围内的勒索软件攻击活动愈演愈烈&#xff0c;受害者数量创下历史新高&#xff0c;同比增长了46%。 例如&#xff0c;2023年伊始&#xff0c;英国皇家邮政成为了勒索团伙LockBit的大型…

QT 使用redis ,连接并使用

一.redis安装 链接&#xff1a;https://pan.baidu.com/s/17fXKOj5M4VIypR0y5_xtHw 提取码&#xff1a;1234 1.下载得到文件夹如图 course_redis为安装包。 2.启动Redis服务 把安装包解压到某个路径下即可。 打开cmd窗口&#xff0c;切换到Redis安装路径&#xff0c;输入 r…

LLM激活稀疏性加速

相关工作 Deja vu Contextual sparsity for efficient llms at inference time LLM in a flash Efficient Large Language Model Inference with Limited Memory ReLU Strikes Back Exploiting Activation Sparsity in Large Language Models ReLU2 Wins: Discovering Effi…

量子飞跃:从根本上改变复杂问题的解决方式

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 编辑丨王珩 编译/排版丨沛贤 深度好文&#xff1a;1000字丨5分钟阅读 利用多功能量子比特的量子计算机已处于解决复杂优化问题的最前沿&#xff0c;例如旅行商问题&#xff0c;这是一个典型的…

10、【代理模式】通过引入一个代理对象来控制对原始对象的访问的方式。

你好&#xff0c;我是程序员雪球。 今天我们了解代理模式的原理、静态代理和动态代理的区别、Spring AOP 和动态代理的关系、代理模式的使用场景&#xff0c;以及用 Java 实现一个动态代理示例 一、代理模式的原理 代理模式是一种设计模式&#xff0c;它提供了一种通过引入一个…

手把手带你搞懂电压跌落测试DIP

针对很多入门小白不懂元器件&#xff0c;一些老工程师上班很多年有的也不懂得总结知识点&#xff0c;以及想学习不知道怎么系统学习的这一类人群&#xff0c;前方知识点来袭&#xff0c;请君放心食用~ 一&#xff0c;项目背景介绍 最近做项目过程中&#xff0c;客户要求要做电…

wps使用Latex编辑公式没有Latex formula

wps使用Latex编辑公式没有Latex formula 1. 下载CTEX2. 下载LaTeXEE3. 配置Miktex4. 配置latexee5. 用管理员权限运行latexeqedit.exe6. wps插入latex公式 1. 下载CTEX 下载CTEX网址&#xff0c;我下载的下图这个&#xff0c;下载完了之后运行exe文件安装ctex。 2. 下载LaTe…