• 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

    1. package com.example.demo;
    2. import org.springframework.context.annotation.Configuration;
    3. import org.springframework.web.socket.config.annotation.EnableWebSocket;
    4. import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
    5. import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
    6. @Configuration
    7. @EnableWebSocket
    8. public class WebSocketConfig implements WebSocketConfigurer {
    9. @Override
    10. public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
    11. registry.addHandler(new MyWebSocketHandler(), "/websocket")
    12. .setAllowedOrigins("*");
    13. }
    14. }
    2.2 创建 WebSocket 处理器

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

    1. package com.example.demo;
    2. import org.springframework.web.socket.CloseStatus;
    3. import org.springframework.web.socket.TextMessage;
    4. import org.springframework.web.socket.WebSocketSession;
    5. import org.springframework.web.socket.handler.TextWebSocketHandler;
    6. import java.util.Collections;
    7. import java.util.HashSet;
    8. import java.util.Set;
    9. public class MyWebSocketHandler extends TextWebSocketHandler {
    10. private static Set sessions =
    11. Collections.synchronizedSet(new HashSet<>());
    12. @Override
    13. public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    14. sessions.add(session);
    15. }
    16. @Override
    17. public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
    18. for (WebSocketSession webSocketSession : sessions) {
    19. if (webSocketSession.isOpen() && !session.getId().equals(webSocketSession.getId())) {
    20. webSocketSession.sendMessage(new TextMessage(message.getPayload()));
    21. }
    22. }
    23. }
    24. @Override
    25. public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
    26. sessions.remove(session);
    27. }
    28. }

    3. 创建 WebSocket 客户端

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

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

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>WebSocket Testtitle>
    6. head>
    7. <body>
    8. <h1>WebSocket Testh1>
    9. <input type="text" id="messageInput" placeholder="Enter message">
    10. <button onclick="sendMessage()">Sendbutton>
    11. <ul id="messages">ul>
    12. <script>
    13. let websocket = new WebSocket("ws://localhost:8080/websocket");
    14. websocket.onopen = function(event) {
    15. console.log("Connected to WebSocket");
    16. };
    17. websocket.onmessage = function(event) {
    18. let messages = document.getElementById("messages");
    19. let message = document.createElement("li");
    20. message.textContent = event.data;
    21. messages.appendChild(message);
    22. };
    23. websocket.onclose = function(event) {
    24. console.log("Disconnected from WebSocket");
    25. };
    26. function sendMessage() {
    27. let input = document.getElementById("messageInput");
    28. websocket.send(input.value);
    29. input.value = '';
    30. }
    31. script>
    32. body>
    33. html>

    4. 运行 Spring Boot 应用程序

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

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

    1. package com.example.demo;
    2. import org.springframework.boot.SpringApplication;
    3. import org.springframework.boot.autoconfigure.SpringBootApplication;
    4. @SpringBootApplication
    5. public class DemoApplication {
    6. public static void main(String[] args) {
    7. SpringApplication.run(DemoApplication.class, args);
    8. }
    9. }

    5. 测试 WebSocket

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

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

    6、效果展示

    7、注解的写法

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

    创建一个配置类 WebSocketConfig.java:

    1. package com.example.demo;
    2. import org.springframework.context.annotation.Configuration;
    3. import org.springframework.web.socket.server.standard.ServerEndpointExporter;
    4. @Configuration
    5. public class WebSocketConfig {
    6. public ServerEndpointExporter serverEndpointExporter() {
    7. return new ServerEndpointExporter();
    8. }
    9. }

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

    1. package com.example.demo;
    2. import javax.websocket.OnClose;
    3. import javax.websocket.OnError;
    4. import javax.websocket.OnMessage;
    5. import javax.websocket.OnOpen;
    6. import javax.websocket.Session;
    7. import javax.websocket.server.ServerEndpoint;
    8. import java.io.IOException;
    9. import java.util.Collections;
    10. import java.util.HashSet;
    11. import java.util.Set;
    12. @ServerEndpoint("/websocket")
    13. public class WebSocketServer {
    14. private static Set clients = Collections.synchronizedSet(new HashSet<>());
    15. @OnOpen
    16. public void onOpen(Session session) {
    17. clients.add(session);
    18. System.out.println("New connection with client id: " + session.getId());
    19. }
    20. @OnMessage
    21. public void onMessage(String message, Session session) throws IOException {
    22. System.out.println("New message from client id: " + session.getId() + ": " + message);
    23. for (Session client : clients) {
    24. if (!client.getId().equals(session.getId())) {
    25. client.getBasicRemote().sendText(message);
    26. }
    27. }
    28. }
    29. @OnClose
    30. public void onClose(Session session) {
    31. clients.remove(session);
    32. System.out.println("Connection closed with client id: " + session.getId());
    33. }
    34. @OnError
    35. public void onError(Session session, Throwable throwable) {
    36. System.out.println("Error from client id: " + session.getId());
    37. throwable.printStackTrace();
    38. }
    39. }

    其他地方和上面的一样。

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

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

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

    2、连接管理

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

    3、数据传输

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

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

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

    4、安全性

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

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

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

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

    5、性能优化

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

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

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

    6、服务器架构

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

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

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

  • 相关阅读:
    素数和_C语言
    code-push热部署开发者端
    一文看懂MySQL的行锁
    Leetcode64. 最小路径和
    采用 Phi-3 小型模型和 Elastic 的智能订购系统
    【机器学习基础】机器学习的模型评估(评估方法及性能度量原理及主要公式)
    日志打印管理
    几个神器来拯救自己奇丑无比的python代码
    OTG 配置为U盘
    设计模式-原型模式
  • 原文地址:https://blog.csdn.net/a2285786446/article/details/139645617