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依赖

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

 2.WebSocke配置类

package com.example.websocketdemo;

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 // 启用WebSocket支持
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        // 注册WebSocket处理程序,并设置WebSocket路径为 "/websocket"
        registry.addHandler(new MyWebSocketHandler(), "/websocket").setAllowedOrigins("*");
    }
}

 3.WebSocke服务类

package com.example.websocketdemo;

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 {

    // 用于存储所有活动的WebSocket会话
    private static final Set<WebSocketSession> sessions = Collections.synchronizedSet(new HashSet<>());

    // 处理接收到的文本消息
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload(); // 获取消息内容
        System.out.println("Received: " + payload); // 打印接收到的消息
        session.sendMessage(new TextMessage("Server received: " + payload)); // 回复消息给客户端

        // 发送当前连接人数
        broadcast("Current number of connections: " + sessions.size());
    }

    // 处理WebSocket连接建立
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        sessions.add(session); // 添加会话到集合
        System.out.println("Connected: " + session.getId());

        // 发送当前连接人数
        broadcast("New connection established. Current number of connections: " + sessions.size());
    }

    // 处理WebSocket连接关闭
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        sessions.remove(session); // 从集合中移除会话
        System.out.println("Disconnected: " + session.getId());

        // 发送当前连接人数
        broadcast("Connection closed. Current number of connections: " + sessions.size());
    }

    // 向所有连接的客户端广播消息
    private void broadcast(String message) {
        for (WebSocketSession session : sessions) {
            if (session.isOpen()) {
                try {
                    session.sendMessage(new TextMessage(message));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

  3.创建启动类

package com.example.websocketdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class WebsocketDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(WebsocketDemoApplication.class, args); // 启动Spring Boot应用
    }
}

四、测试WebSocket连接

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

let socket = new WebSocket("ws://localhost:8080/websocket");

socket.onopen = function(e) {
  console.log("[open] Connection established");
  socket.send("Hello Server!"); // 发送消息给服务器
};

socket.onmessage = function(event) {
  console.log(`[message] Data received from server: ${event.data}`); // 处理服务器返回的消息
};

socket.onclose = function(event) {
  if (event.wasClean) {
    console.log(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
  } else {
    console.error('[close] Connection died'); // 处理连接关闭
  }
};

socket.onerror = function(error) {
  console.error(`[error] ${error.message}`); // 处理错误
};

WebSocket是一种基于TCP的网络协议,它实现了浏览器与服务器之间的全双工通信,允许服务器主动向客户端推送信息,从而实现实时数据推送的功能。\[3\] 在使用WebSocket实现实时推送数据的过程中,需要在前后端分别进行相应的配置和代码编写。 在后端,需要创建一个WebSocket服务器,并在服务器端代码中编写发送消息的逻辑。可以使用Java的Spring框架提供的WebSocket支持,通过@EnableScheduling注解开启定时任务,并在定时任务中调用WebSocket服务器的sendAllMessage方法发送消息。\[2\] 在前端,需要使用JavaScript代码来建立WebSocket连接,并监听服务器端发送的消息。可以使用WebSocket的API来创建WebSocket对象,并通过onmessage事件监听服务器端发送的消息。一旦接收到消息,就可以进行相应的处理,例如更新页面上的数据。\[1\] 通过以上的配置和代码编写,就可以实现WebSocket实时推送数据的功能。当服务器端有新的数据需要推送时,会主动发送消息给客户端,客户端接收到消息后可以进行相应的处理,实现实时更新数据的效果。 #### 引用[.reference_title] - *1* *3* [webSocket实现数据实时推送(附:前后端代码)](https://blog.csdn.net/weixin_42555014/article/details/124140649)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [SpringBoot集成WebSocket实现消息实时推送(提供Gitee源码)](https://blog.csdn.net/HJW_233/article/details/131326572)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

钟月一人

码字整理不易,感谢各位大佬支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值