WebSocket是一种网络通信协议,旨在实现客户端和服务器之间的双向、全双工通信。它在HTML5规范中被引入,用于替代基于传统HTTP协议的长轮询、轮询和流传输等方式,以提供更高效的实时数据传输。
双向通信:与传统的HTTP协议不同,WebSocket允许客户端和服务器之间的双向通信。客户端和服务器都可以在任何时候发送数据,而无需等待对方先发起请求。
持久连接:WebSocket连接一旦建立,将会保持打开状态,直到客户端或服务器主动关闭连接。这减少了因频繁建立和关闭连接带来的开销。
低延迟:由于WebSocket减少了请求头信息和频繁的握手过程,通信延迟显著降低,非常适合实时应用。
基于消息:WebSocket通信是基于消息的,而不是基于请求-响应。这样可以更加灵活地传输数据。
握手阶段:客户端通过HTTP请求向服务器发起WebSocket握手请求。这个请求包含一个特殊的Upgrade头部,指示服务器将连接从HTTP升级到WebSocket协议。
建立连接:服务器收到握手请求后,如果同意升级连接,则会返回一个101状态码的响应,表示协议切换成功。此时,WebSocket连接正式建立。
数据传输:连接建立后,客户端和服务器可以通过WebSocket协议相互发送消息。这些消息可以是文本或二进制数据。
关闭连接:当任意一方不再需要连接时,可以发送关闭请求来关闭WebSocket连接。连接关闭后,通信停止,资源释放。
1.pom.xml添加WebSocke依赖
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-websocketartifactId>
- 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
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应用
- }
- }
可以使用浏览器的控制台进行测试:
- 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}`); // 处理错误
- };