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.rhkb.cn/news/352250.html

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

相关文章

Novartis诺华制药社招综合能力性格动机问卷入职测评笔试题库答案及包过助攻

【华东同舟求职】由资深各行业从业者建立的一站式人才服务网络平台&#xff0c;现阶段目标是“提升全市场各行业岗位信息的流动性和透明度”。我们接受众多行业机构的直接委托发布&#xff0c;并尽力通过各种方法搜寻高价值岗位信息。事实上&#xff0c;我们以发现不为人知的优…

网站改成HTTPS方法

网站改成HTTPS只要网站没有特殊性的要求&#xff0c;绝大部分网站很轻松的就可以完成&#xff0c;尤其是CMS类似的网站系统或者自助搭建的网站&#xff08;比如&#xff1a;这种网站可以在网站后台一次性安装并且生效&#xff09;。 基本要求 将网站改成HTTPS有2个前提&#…

HQChart实战教程73-仿tradingview指标MACD

HQChart实战教程73-仿tradingview指标MACD MACD![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/84d180b5620940f6b9fe08c6f10eb0f3.png)麦语法脚本实心MACD指标脚本效果 空心MACD指标脚本效果图 自定义指标添加到系统指标里HQChart插件源码地址 MACD tradingview中…

智能不锈钢氮气柜温湿度氧含量控制介绍

智能不锈钢氮气柜通过集成精密的温湿度和氧含量控制系统&#xff0c;确保内部环境稳定在适宜存储敏感物料的条件。具体实现方式如下&#xff1a; 温度控制&#xff1a;智能氮气柜通常配备有精确的温度传感器以及加热或冷却系统。当内部温度偏离设定值时&#xff0c;系统会自动启…

ue5创建地图瓦片

先在虚幻商城下载免费的paperzd插件&#xff0c;并启用。 导入资源后&#xff0c;先通过应用paper2d纹理资源&#xff0c;将去掉导入ue时产生的边缘模糊&#xff0c;再点击下面的创建瓦片集&#xff0c; 打开瓦片集&#xff0c;发现选中不对&#xff0c; 改变瓦片大小为16*…

Nature 苏浩团队发表创新人工智能“仿真中学习”框架,实现外骨骼的智能性和通用性

北京时间2024年6月12日23时&#xff0c;美国北卡罗来纳州立大学与北卡罗来纳大学教堂山分校的苏浩团队在《自然》&#xff08;Nature&#xff09;上发表了一篇关于机器人和人工智能算法相结合服务人类的突破性研究论文&#xff0c;标题为“Experiment-free Exoskeleton Assista…

振动分析-3-基于Python的FFT幅值修正与能量修正

幅值修正与能量修正过程&#xff08;更正&#xff09; 参考什么是泄漏&#xff1f; 参考什么是窗函数? 参考使用python实现快速傅里叶变换&#xff08;FFT&#xff09; 参考频谱泄露和窗函数以及加窗后幅度修正和python代码实现 1 快速傅里叶变换(FFT) 离散傅里叶变换(discr…

configure: error: library ‘crypto‘ is required for OpenSSL

1、执行命令&#xff1a;./configure --prefix/opt/app/postgresql --with-openssl 报错&#xff1a; 2、解决办法 执行命令&#xff1a;yum install openssl-devel 重新执行 ./configure --prefix/opt/app/postgresql --with-openssl

Springboot 开发之任务调度框架(一)Quartz 简介

一、引言 常见的定时任务框架有 Quartz、elastic-job、xxl-job等等&#xff0c;本文主要介绍 Spirng Boot 集成 Quartz 定时任务框架。 二、Quartz 简介 Quartz 是一个功能强大且灵活的开源作业调度库&#xff0c;广泛用于 Java 应用中。它允许开发者创建复杂的调度任务&…

C++ 03 之 命名空间

game_kun.cpp #include "game_kun.h"void kun::atk() {cout << "吃鸡的攻击"<< endl; } game_lol.cpp #include "game_lol.h"void lol::atk() {cout << "lol的攻击"<< endl; } game_kun.h #include <…

Linux驱动开发-01配置开发环境

一、配置网络环境 使用桥接网卡时 Ubuntu 就是使用一个真实的网卡 &#xff1a;开发板的网线也连接到这个真实的网卡上&#xff0c;这样 Windows 、 Ubuntu 、开发板就都可以用过这个网卡互通了。 NAT 网卡&#xff1a; Ubuntu 通过它上网&#xff0c;只要 Windows 能上网&…

电商客服的得力助手:快捷回复软件

随着技术的进步&#xff0c;传统的人工打字已经逐渐不能满足快节奏的电商服务需求。如今&#xff0c;市面上涌现出众多快捷回复辅助软件&#xff0c;它们以高效率的特点&#xff0c;成为电商客服人员的必备工具。 作为一名拥有五年经验的电商客服&#xff0c;我深刻体会到了这类…

使用 cx_Oracle 在 Oracle 中等待记录并执行操作

问题背景&#xff1a; 在第一个 Python 项目中&#xff0c;需要等待记录被插入 Oracle 表中&#xff0c;一旦记录存在&#xff0c;就调用 Python 函数。目前使用 cx_Oracle 库&#xff0c;采用一种无限循环的方式来查询表。如果记录存在&#xff0c;就调用函数&#xff0c;然后…

【leetcode刷题】面试经典150题 , 27. 移除元素

leetcode刷题 面试经典150 27. 移除元素 难度&#xff1a;简单 文章目录 一、题目内容二、自己实现代码2.1 方法一&#xff1a;直接硬找2.1.1 实现思路2.1.2 实现代码2.1.3 结果分析 2.2 方法二&#xff1a;排序整体删除再补充2.1.1 实现思路2.1.2 实现代码2.1.3 结果分析 三、…

如何修改倍福CX7000PLC IP地址

我们可以通过登录网页修改PLC的IP地址,这个需要我们知道PLC的初始IP地址,倍福常用学习网址如下: 课程: EPC 产品概要 | 倍福虚拟学院https://tr.beckhoff.com.cn/course/view.php?id=19#section-31、浏览器直接输入PLC 的IP地址 2、点击修改按钮(就是那个旋转) 修改IP地…

【图像分割】DSNet: A Novel Way to Use Atrous Convolutions in Semantic Segmentation

DSNet: A Novel Way to Use Atrous Convolutions in Semantic Segmentation 论文链接&#xff1a;http://arxiv.org/abs/2406.03702 代码链接&#xff1a;https://github.com/takaniwa/DSNet 一、摘要 重新审视了现代卷积神经网络&#xff08;CNNs&#xff09;中的atrous卷积…

针对微电网中可时移,柔性,基础负荷的电价响应模型---代码解析

前言&#xff1a; 在上两篇帖子中&#xff0c;讲解了我对于粒子群算法的理解&#xff0c;站在巨人的肩膀上去回望&#xff1a;科研前辈们确实非常牛逼&#xff0c;所以它才成为了非常经典的算法。这篇帖子主要是想分享一下&#xff0c;对于微电网、电力系统的论文中&#xff0c…

“深入探讨Redis主从复制:原理、配置与优化“

目录 # 概念 1. 配置主从同步步骤 1.1 创建文件夹 1.2 复制配置文件 1.3 配置文件关闭 1.4 查看端口号&#xff0c;发现端口号存在 1.5 连接三个端口号 1.6 查看主机运行情况 1.7 让服务器变成&#xff08;主机&#xff09;或&#xff08;从机&#xff09; 1.8 实现效…

CSS选择符和可继承属性

属性选择符&#xff1a; 示例&#xff1a;a[target"_blank"] { text-decoration: none; }&#xff08;选择所有target"_blank"的<a>元素&#xff09; /* 选择所有具有class属性的h1元素 */ h1[class] { color: silver; } /* 选择所有具有hre…

志愿服务管理系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;基础数据管理&#xff0c;广场论坛管理&#xff0c;志愿活动管理&#xff0c;活动报名管理 前台账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;志愿活动&a…