WebSocket 详解--spring boot简单使用案例

一、什么是WebSocket

WebSocket 是一种网络通信协议,专为在单个 TCP 连接上进行全双工通信而设计。WebSocket 允许客户端和服务器之间的消息能够实时双向传输。这与传统的 HTTP 请求-响应模式有很大的不同。

二、WebSocket 的关键特性

  • 双向通信:WebSocket 提供了双向通信通道。客户端和服务器可以随时向对方发送消息,而无需客户端发起请求。

  • 持久连接:一旦 WebSocket 连接建立,连接将保持打开状态,直到客户端或服务器显式关闭它。这样避免了频繁的 HTTP 请求开销。

  • 低延迟:由于连接保持打开状态,WebSocket 消息的传输延迟非常低,非常适合需要快速响应的应用,如在线游戏、实时聊天等。

  • 轻量协议:WebSocket 协议头部相对较小,减少了数据传输的开销。

三、WebSocket 工作原理

  • 握手:WebSocket 连接始于 HTTP 请求。客户端发出一个带有特殊头部的 HTTP 请求,要求升级到 WebSocket 协议。服务器同意后,通过 HTTP 101 状态码响应,表示协议切换。

  • 数据传输:握手完成后,客户端和服务器之间的通信切换到 WebSocket 协议。两者可以在这条连接上随时发送文本或二进制消息。

  • 连接关闭:连接可以由客户端或服务器主动关闭,通过发送关闭消息并随后关闭 TCP 连接。

四、WebSocket 应用场景

  1. 实时聊天应用:如在线客服、社交网络聊天。
  2. 在线游戏:需要低延迟实时通信的多人游戏。
  3. 实时数据流:如股票行情、体育比分更新。
  4. 协同编辑:如 Google Docs 这样的实时文档编辑工具。
  5. 物联网(IoT)设备:需要与服务器持续通信的智能设备。

WebSocket 的优势在于其双向通信能力和低延迟,是需要实时数据更新的应用的不二选择。

五、WebSocket简单使用案例——java为例

1、为了方便部署,直接创建一个spring boot项目

首先,使用 Spring Initializr 创建一个新的 Spring Boot 项目。你可以访问 Spring Initializr 或者在 IntelliJ IDEA 中创建一个新项目。

选择的依赖项

  • Spring Web
  • Spring Boot Starter WebSocket

下载项目并解压到你的工作目录中。

2. 编写 WebSocket 服务器端点

2.1 创建 WebSocket 配置类

src/main/java/com/example/demo 下创建一个配置类 WebSocketConfig.java

package com.example.demo;import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(new MyWebSocketHandler(), "/websocket").setAllowedOrigins("*");}
}
2.2 创建 WebSocket 处理器

在同一包下创建一个处理器类 MyWebSocketHandler.java

package com.example.demo;import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;import java.util.Collections;
import java.util.HashSet;
import java.util.Set;public class MyWebSocketHandler extends TextWebSocketHandler {private static Set<WebSocketSession> sessions = Collections.synchronizedSet(new HashSet<>());@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {sessions.add(session);}@Overridepublic void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {for (WebSocketSession webSocketSession : sessions) {if (webSocketSession.isOpen() && !session.getId().equals(webSocketSession.getId())) {webSocketSession.sendMessage(new TextMessage(message.getPayload()));}}}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {sessions.remove(session);}
}

3. 创建 WebSocket 客户端

为了测试 WebSocket,我们可以创建一个简单的 HTML 文件和 JavaScript 客户端。

src/main/resources/static 下创建一个新的 HTML 文件 index.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>WebSocket Test</title>
</head>
<body><h1>WebSocket Test</h1><input type="text" id="messageInput" placeholder="Enter message"><button onclick="sendMessage()">Send</button><ul id="messages"></ul><script>let websocket = new WebSocket("ws://localhost:8080/websocket");websocket.onopen = function(event) {console.log("Connected to WebSocket");};websocket.onmessage = function(event) {let messages = document.getElementById("messages");let message = document.createElement("li");message.textContent = event.data;messages.appendChild(message);};websocket.onclose = function(event) {console.log("Disconnected from WebSocket");};function sendMessage() {let input = document.getElementById("messageInput");websocket.send(input.value);input.value = '';}</script>
</body>
</html>

4. 运行 Spring Boot 应用程序

打开你的 IDE(如 IntelliJ IDEA),加载项目并运行 Spring Boot 应用程序。

你可以通过运行 DemoApplication.java 主类来启动应用程序:

package com.example.demo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}

5. 测试 WebSocket

启动应用程序后,打开浏览器并访问 http://localhost:8080。你应该看到一个简单的页面,允许你输入消息并发送。消息将通过 WebSocket 发送到服务器,并广播到所有连接的客户端。

这是一个使用 Spring Boot 和注解配置的 WebSocket 完整示例。这个示例展示了如何使用注解简化 WebSocket 的配置和处理。你可以根据需要进一步扩展和定制这个项目。

6、效果展示

7、注解的写法

直接使用注解包括 @OnOpen, @OnMessage, @OnClose, @OnError等去配置websocket

创建一个配置类 WebSocketConfig.java:

package com.example.demo;import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;@Configuration
public class WebSocketConfig {public ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}

在同一包下创建 WebSocket 端点类 WebSocketServer.java

package com.example.demo;import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;@ServerEndpoint("/websocket")
public class WebSocketServer {private static Set<Session> clients = Collections.synchronizedSet(new HashSet<>());@OnOpenpublic void onOpen(Session session) {clients.add(session);System.out.println("New connection with client id: " + session.getId());}@OnMessagepublic void onMessage(String message, Session session) throws IOException {System.out.println("New message from client id: " + session.getId() + ": " + message);for (Session client : clients) {if (!client.getId().equals(session.getId())) {client.getBasicRemote().sendText(message);}}}@OnClosepublic void onClose(Session session) {clients.remove(session);System.out.println("Connection closed with client id: " + session.getId());}@OnErrorpublic void onError(Session session, Throwable throwable) {System.out.println("Error from client id: " + session.getId());throwable.printStackTrace();}
}

其他地方和上面的一样。

六、实际开发可能需要考虑的相关问题

1、处理客户端断网的策略。

  • 心跳检测:定期发送心跳消息以确保连接的有效性。
  • 超时处理:在特定时间内未收到客户端的消息或心跳回应时关闭连接。
  • 异常处理:捕获并处理连接异常,如断网错误。

2、连接管理

  • 连接断开和重连:客户端可能会由于网络波动、服务器重启等原因导致连接断开。需要实现自动重连机制。
    • 解决方案:客户端实现自动重连,服务器端实现连接状态的监控和重连处理。
  • 连接数量限制:服务器可能会面临大量的并发连接,需要管理连接的生命周期。
    • 解决方案:使用连接池、限制单个用户的最大连接数、负载均衡。

3、数据传输

  • 消息顺序:WebSocket 是全双工通信,消息可能会乱序到达。

    • 解决方案:在消息中添加序列号,客户端根据序列号重排消息。
  • 消息大小:某些应用可能需要传输大数据,WebSocket 本身对消息大小有一定限制。

    • 解决方案:将大消息分割成小块发送,在客户端重新组装。

4、安全性

  • 数据加密:WebSocket 传输的数据可以被中间人截获。

    • 解决方案:使用 wss:// 协议(基于 TLS 加密的 WebSocket)确保传输安全。
  • 身份验证和授权:需要确保只有经过认证和授权的客户端才能建立 WebSocket 连接。

    • 解决方案:在握手阶段进行身份验证,使用 JWT 或其他令牌机制。
  • 跨站脚本攻击 (XSS):WebSocket 可能成为 XSS 攻击的目标。

    • 解决方案:在服务器端验证和过滤输入数据,确保数据格式和内容安全。

5、性能优化

  • 延迟:需要尽量减少消息传输的延迟。

    • 解决方案:优化网络路径、使用更快的服务器、减少数据量。
  • 带宽消耗:频繁的消息传输会消耗大量带宽。

    • 解决方案:压缩消息、优化数据结构。

6、服务器架构

  • 扩展性:需要确保 WebSocket 服务器能处理大量并发连接。

    • 解决方案:使用集群和负载均衡,将连接分配到多个服务器上。
  • 高可用性:需要确保服务器在出现故障时能迅速恢复。

    • 解决方案:使用容错和故障转移机制,配置多个冗余服务器。

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

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

相关文章

【StableDiffusion】Prompts 提示词语法;高阶用法;写作顺序是什么,先写什么后写什么

Prompt 写作顺序 第一步&#xff1a;画质词画风词 第一步先写“画质词”和“画风词” 画质词如下&#xff1a; 画风词如下&#xff1a; 第二步&#xff1a;画面主体描述 人物性别、年龄、发型、发色、情绪表情、衣服款式、衣服颜色、动作、饰品、身材、五官微调 第三步&…

多表联查小情景例子

这里有个需求&#xff1a; 需要给定套餐表setmeal 的 id 查询这个套餐内的所有菜品 dish 实际上如果可能&#xff0c;只需要查询套餐菜品表(setmeal_dish)&#xff0c;查看一个套餐内包含包含的所有菜品&#xff0c;然后把这些菜品全部取出即可。 看一下setmeal_dish 表&…

ZnO电阻片在低电场区域的泄漏电流及其电阻的负温度系数

在低电场区域,流过ZnO非线性电阻的泄漏电流小于1mA.泄漏电流不仅与施加的电压幅值有关,而且与温度高低有关。图2.6表示温度对泄漏电流的影响,温度越高,电子在电场作用下定向的运动就越激烈,导致泄漏电流增大。因此温度升高将导致电阳值下降,即ZnO 电阻呈现负温度特性。 一般以…

centos下创建raid6磁盘阵列

在CentOS系统中创建RAID 6阵列&#xff0c;可以使用mdadm工具。 以下是创建RAID 6阵列的基本步骤和示例代码&#xff1a; 安装mdadm工具&#xff08;如果尚未安装&#xff09;&#xff1a; sudo yum install mdadm 假设你有至少四个以上的磁盘设备&#xff08;例如 /dev/sdi…

STM32存储左右互搏 模拟U盘桥接SPI总线FATS读写FLASH W25QXX

STM32存储左右互搏 模拟U盘桥接SPI总线FATS读写FLASH W25QXX STM32的USB接口可以模拟成为U盘&#xff0c;通过FATS文件系统对连接的存储单元进行U盘方式的读写。 这里介绍STM32CUBEIDE开发平台HAL库模拟U盘桥接SPI总线FATS读写W25Q各型号FLASH的例程。 FLASH是常用的一种非易失…

maven archetype项目构架

1、设置环境变量 set MAVEN_HOMED:\SF\java\apache-maven-3.6.3 set path%path%;%MAVEN_HOME%\bin;2、制作archetype mvn -s "D:\SF\java\apache-maven-3.6.3\conf\settings.xml" archetype:create-from-project -DpackageNamecom.demo.esb-s:指定maven的setting文…

LeetCode | 28.找出字符串中第一个匹配项的下标 KMP

这是字符串匹配问题&#xff0c;朴素做法是两重遍历&#xff0c;依次从主串的i位置开始查看是否和模式串匹配&#xff0c;若不匹配就换下一个位置进行判断&#xff0c;直到找到或者遍历完&#xff0c;时间复杂度 O ( m n ) O(m \times n) O(mn) 还可以对主串进行处理&#xff…

vue.js+node.js+mysql在线聊天室源码

vue.jsnode.jsmysql在线聊天室源码 技术栈&#xff1a;vue.jsElement UInode.jssocket.iomysql vue.jsnode.jsmysql在线聊天室源码

单例模式、工厂模式 c++关键字 static

static 关键字的作用&#xff1a; 主要作用在于 控制变量或函数的作用域、生命周期以及它们如何被不同部分的程序访问&#xff0c;从而帮助程序员管理内存、避免命名冲突&#xff0c;并实现特定的设计模式&#xff08;如单例模式&#xff09;。 1. 静态局部变量&#xff1a;当…

区间预测 | Matlab实现EVO-CNN-SVM能量谷算法优化卷积神经网络支持向量机结合核密度估计多置信区间多变量回归区间预测

区间预测 | Matlab实现EVO-CNN-SVM能量谷算法优化卷积神经网络支持向量机结合核密度估计多置信区间多变量回归区间预测 目录 区间预测 | Matlab实现EVO-CNN-SVM能量谷算法优化卷积神经网络支持向量机结合核密度估计多置信区间多变量回归区间预测效果一览基本介绍程序设计参考资…

5.3 Python 闭包函数,递归函数,匿名函数

1. 函数对象 Python中所有的数据都是对象, 函数的值也是一个对象, 通过函数名获取函数对象. 使用函数名也就是使用函数对象, 函数对象加上括号立刻执行函数体代码块. 函数名的其它作用: * 1. 函数名可以作为其它变量的值. * 2. 函数名可以作为其它函数的参数. * 3. 函数名可以…

搜索与图论:染色法判别二分图

搜索与图论&#xff1a;染色法判别二分图 题目描述参考代码 题目描述 输入样例 4 4 1 3 1 4 2 3 2 4输出样例 Yes参考代码 #include <cstring> #include <iostream> #include <algorithm>using namespace std;const int N 100010, M 200010;int n, m; i…

多款可观测产品全面升级丨阿里云云原生 5 月产品月报

云原生月度动态 云原生是企业数字创新的最短路径。 《阿里云云原生每月动态》&#xff0c;从趋势热点、产品新功能、服务客户、开源与开发者动态等方面&#xff0c;为企业提供数字化的路径与指南。 趋势热点 &#x1f947; 阿里云云原生产品负责人李国强&#xff1a;推进可…

《Brave New Words 》9.1 AI 世界中的就业

Part IX: Work and What Comes Next 第九部分&#xff1a;工作及其未来发展 The one who plants trees, knowing that he will never sit in their shade, has at least started to understand the meaning of life. —Rabindranath Tagore 种树的人&#xff0c;虽然知道他永远…

如何舒适的使用VScode

安装好VScode后通常会很不好用&#xff0c;以下配置可以让你的VScode变得好用许多。 VScode的配置流程 1、设置VScode中文2、下载C/C拓展&#xff0c;使代码可以跳转3、更改编码格式4、设置滚轮缩放5、设置字体6、设置保存自动改变格式7、vscode设置快捷代码8、下载插件并学会…

Java多线程面试重点-1

0. 什么是并发&#xff1f;什么是并行&#xff1f; 并发&#xff1a;把时间分成一段一段&#xff0c;每个线程轮流抢占时间段。 如果时间段非常短&#xff0c;线程切换非常快&#xff0c;被称为伪并行。并行&#xff1a;多个线程可以同时运行。 并发与并行造成的影响&#xff…

ARM32开发--IIC软实现

知不足而奋进 望远山而前行 目录 文章目录 前言 开发流程 GD32F4软件I2C初始化 GD32F4软件I2C引脚功能 写操作 读操作 总结 前言 在嵌入式系统开发中&#xff0c;软件实现的I2C通信协议扮演着至关重要的角色。本文将深入探讨如何在GD32F4系列微控制器上实现软件I2C功能…

深入浅出 Go 语言的 GPM 模型(Go1.21)

引言 在现代软件开发中&#xff0c;有效地利用并发是提高应用性能和响应速度的关键。随着多核处理器的普及&#xff0c;编程语言和框架如何高效、简便地支持并发编程&#xff0c;成为了软件工程师们评估和选择工具时的一个重要考量。在这方面&#xff0c;Go 语言凭借其创新的并…

Python的Pillow(图像处理库)非常详细的学习笔记

Python的Pillow库是一个非常强大的图像处理库。 安装Pillow库&#xff1a; 在终端或命令行中输入以下命令来安装Pillow&#xff1a; pip install pillow 安装后查看是否安装成功以及当前版本 pip show Pillow 升级库&#xff1a; pip install pillow --upgrade 一些基…