• WebSocket实现前后端双向数据的实时推送


    一、WebSocket简介

            WebSocket是一种网络通信协议,旨在实现客户端和服务器之间的双向、全双工通信。它在HTML5规范中被引入,用于替代基于传统HTTP协议的长轮询、轮询和流传输等方式,以提供更高效的实时数据传输。

    WebSocket的特点

    1. 双向通信:与传统的HTTP协议不同,WebSocket允许客户端和服务器之间的双向通信。客户端和服务器都可以在任何时候发送数据,而无需等待对方先发起请求。

    2. 持久连接WebSocket连接一旦建立,将会保持打开状态,直到客户端或服务器主动关闭连接。这减少了因频繁建立和关闭连接带来的开销。

    3. 低延迟:由于WebSocket减少了请求头信息和频繁的握手过程,通信延迟显著降低,非常适合实时应用。

    4. 基于消息:WebSocket通信是基于消息的,而不是基于请求-响应。这样可以更加灵活地传输数据。

    WebSocket的工作原理

    1. 握手阶段:客户端通过HTTP请求向服务器发起WebSocket握手请求。这个请求包含一个特殊的Upgrade头部,指示服务器将连接从HTTP升级到WebSocket协议。

    2. 建立连接:服务器收到握手请求后,如果同意升级连接,则会返回一个101状态码的响应,表示协议切换成功。此时,WebSocket连接正式建立。

    3. 数据传输:连接建立后,客户端和服务器可以通过WebSocket协议相互发送消息。这些消息可以是文本或二进制数据。

    4. 关闭连接:当任意一方不再需要连接时,可以发送关闭请求来关闭WebSocket连接。连接关闭后,通信停止,资源释放。

    二、数据实时推送的实现方式和应用场景

    轮询 (Polling)

    优点
    1. 实现简单:实现和理解起来相对容易,使用传统的HTTP请求。
    2. 浏览器兼容性好:几乎所有浏览器都支持,适用于所有的客户端。
    缺点
    1. 资源浪费:频繁的HTTP请求会消耗大量带宽和服务器资源,即使没有新数据时也会发送请求。
    2. 延迟高:实时性差,因为需要等待下一个请求周期才能获取新数据。
    使用场景
    • 适用于低频更新和对实时性要求不高的应用,如定时刷新页面内容。

    长连接 (HTTP Persistent Connection)

    优点
    1. 减少开销:在同一个TCP连接上进行多个HTTP请求,减少了建立和关闭连接的开销。
    2. 提高效率:适用于连续请求的场景,提高了传输效率。
    缺点
    1. 资源占用:服务器需要维护连接状态,占用资源。
    2. 不适合实时通信:虽然减少了建立连接的开销,但仍然是基于请求-响应模式,实时性不如WebSocket。
    使用场景
    • 适用于需要频繁请求数据的应用,如加载大量静态资源的网页。

    WebSocket

    优点
    1. 双向通信:客户端和服务器都可以主动发送消息,实现全双工通信。
    2. 低延迟:一旦连接建立,数据可以实时传输,延迟极低。
    3. 高效:减少了HTTP头部和握手的开销,适合高频率的数据传输。
    缺点
    1. 复杂度高:实现和维护起来比轮询复杂,需要处理连接管理、心跳检测等。
    2. 浏览器兼容性:虽然现代浏览器都支持,但在非常旧的浏览器上可能不支持。
    使用场景
    • 适用于高频率和低延迟的实时应用,如在线游戏、实时聊天、股票行情、协作编辑。

    三、代码实现

    1.pom.xml添加WebSocke依赖

    1. <dependency>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-websocketartifactId>
    4. dependency>

     2.WebSocke配置类

    1. package com.example.websocketdemo;
    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 // 启用WebSocket支持
    8. public class WebSocketConfig implements WebSocketConfigurer {
    9. @Override
    10. public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
    11. // 注册WebSocket处理程序,并设置WebSocket路径为 "/websocket"
    12. registry.addHandler(new MyWebSocketHandler(), "/websocket").setAllowedOrigins("*");
    13. }
    14. }

     3.WebSocke服务类

    1. package com.example.websocketdemo;
    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. // 用于存储所有活动的WebSocket会话
    11. private static final Set sessions = Collections.synchronizedSet(new HashSet<>());
    12. // 处理接收到的文本消息
    13. @Override
    14. protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
    15. String payload = message.getPayload(); // 获取消息内容
    16. System.out.println("Received: " + payload); // 打印接收到的消息
    17. session.sendMessage(new TextMessage("Server received: " + payload)); // 回复消息给客户端
    18. // 发送当前连接人数
    19. broadcast("Current number of connections: " + sessions.size());
    20. }
    21. // 处理WebSocket连接建立
    22. @Override
    23. public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    24. sessions.add(session); // 添加会话到集合
    25. System.out.println("Connected: " + session.getId());
    26. // 发送当前连接人数
    27. broadcast("New connection established. Current number of connections: " + sessions.size());
    28. }
    29. // 处理WebSocket连接关闭
    30. @Override
    31. public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
    32. sessions.remove(session); // 从集合中移除会话
    33. System.out.println("Disconnected: " + session.getId());
    34. // 发送当前连接人数
    35. broadcast("Connection closed. Current number of connections: " + sessions.size());
    36. }
    37. // 向所有连接的客户端广播消息
    38. private void broadcast(String message) {
    39. for (WebSocketSession session : sessions) {
    40. if (session.isOpen()) {
    41. try {
    42. session.sendMessage(new TextMessage(message));
    43. } catch (Exception e) {
    44. e.printStackTrace();
    45. }
    46. }
    47. }
    48. }
    49. }

      3.创建启动类

    1. package com.example.websocketdemo;
    2. import org.springframework.boot.SpringApplication;
    3. import org.springframework.boot.autoconfigure.SpringBootApplication;
    4. @SpringBootApplication
    5. public class WebsocketDemoApplication {
    6. public static void main(String[] args) {
    7. SpringApplication.run(WebsocketDemoApplication.class, args); // 启动Spring Boot应用
    8. }
    9. }

    四、测试WebSocket连接

    可以使用浏览器的控制台进行测试:

    1. let socket = new WebSocket("ws://localhost:8080/websocket");
    2. socket.onopen = function(e) {
    3. console.log("[open] Connection established");
    4. socket.send("Hello Server!"); // 发送消息给服务器
    5. };
    6. socket.onmessage = function(event) {
    7. console.log(`[message] Data received from server: ${event.data}`); // 处理服务器返回的消息
    8. };
    9. socket.onclose = function(event) {
    10. if (event.wasClean) {
    11. console.log(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
    12. } else {
    13. console.error('[close] Connection died'); // 处理连接关闭
    14. }
    15. };
    16. socket.onerror = function(error) {
    17. console.error(`[error] ${error.message}`); // 处理错误
    18. };

  • 相关阅读:
    深度学习入门(十五)环境和分布偏移(了解)
    中英文说明书丨SYSY NeuN抗体参数及应用实例
    Java实现自定义Hive认证账户密码
    信号和槽的绑定
    Unity笔记(15):OnTriggerEnter2D [2D]
    用 pytorch 训练端对端验证码识别神经网络并进行 C++ 移植
    内存的读写过程、现实模型及指针
    Pytorch之RepVGG图像分类
    数据库实践 Hw08
    CentOS 搭建 OpenVPN 服务
  • 原文地址:https://blog.csdn.net/WANGLI123956/article/details/139358768