WebSocket
1. 什么是 WebSocket?
WebSocket 是一种网络通信协议,它在单个 TCP 连接上提供全双工通信(Full-Duplex Communication)的能力,允许服务器和客户端之间实时传输数据。
-
协议特点
- 全双工通信:服务器和客户端可以主动发送消息,而不是传统 HTTP 的请求-响应模式。
- 长连接:建立一次连接后,可以持续使用,直到一方主动关闭。
- 低延迟:消息通过帧(Frame)发送,减少了传统 HTTP 头信息带来的开销。
- 高效率:适合实时性要求高的场景。
-
工作原理
- 握手阶段:客户端通过 HTTP 发起 WebSocket 升级请求,服务端返回
101 Switching Protocols
,连接升级为 WebSocket 协议。 - 通信阶段:在连接建立后,数据通过轻量级的帧格式进行传输。
- 关闭阶段:一方主动发送关闭帧,连接断开。
- 握手阶段:客户端通过 HTTP 发起 WebSocket 升级请求,服务端返回
2. WebSocket 的作用
WebSocket 的主要作用是实现实时通信,即当数据在服务器或客户端发生变化时,可以立即推送到对方,而无需轮询(Polling)或长轮询(Long Polling)。
-
实时数据传输
- WebSocket 可以持续保持连接,无需频繁建立和关闭,适合快速传递实时数据。
-
服务器主动推送
- 服务器可以主动向客户端发送消息,减少客户端对服务器的频繁请求。
-
节省带宽和资源
- WebSocket 消息帧中没有冗余的 HTTP 头部信息,减少了带宽占用。
- 对于高频通信,WebSocket 比传统的 HTTP 更高效。
3. WebSocket 与 HTTP 的区别
特性 | HTTP(传统) | WebSocket(实时) |
---|---|---|
通信模型 | 请求-响应模型,客户端必须发起请求才能获得响应 | 双向通信,服务端和客户端都可以主动发送消息 |
连接状态 | 每次请求建立新的连接 | 连接建立后保持长连接 |
协议头开销 | 每次请求和响应都包含完整的 HTTP 头部信息 | 初次握手后,数据帧格式简单,无头部冗余 |
适用场景 | 低频通信、非实时性场景 | 高频通信、实时性要求高的场景 |
4. WebSocket 在 Java 开发中的使用场景
1.实时聊天系统
- 场景描述:聊天室、私聊、群聊。
- 实现功能:
- 用户之间实时发送和接收消息。
- 服务器广播消息给多个用户。
- 优势:相比轮询,WebSocket 的双向通信更高效。
2.实时通知和推送
- 场景描述:例如实时股票价格更新、系统消息推送、用户活动通知。
- 实现功能:
- 服务器可以主动向客户端推送数据。
- 优势:低延迟,用户体验更好。
3.实时数据流
- 场景描述:例如在线游戏的实时状态同步、物联网设备的数据流传输。
- 实现功能:
- 客户端和服务器持续同步状态或传输数据。
- 优势:节省带宽,支持大规模并发。
4.实时协作工具
- 场景描述:例如多人协作文档编辑、实时白板。
- 实现功能:
- 服务器实时广播用户的操作给其他参与者。
- 优势:多用户实时协作,延迟低。
5.在线教育
- 场景描述:实时课堂互动、学生提问、教师推送消息。
- 实现功能:
- 服务器推送教学内容或问题答案。
- 优势:实时互动,提升教学体验。
6.实时监控和仪表盘
- 场景描述:例如服务器运行状态、日志监控、设备运行状态监控。
- 实现功能:
- 实时向用户展示系统状态或日志信息。
- 优势:无需刷新页面即可获得最新状态。
7.在线游戏
- 场景描述:实时多人游戏的状态同步和交互。
- 实现功能:
- 玩家操作即时同步到服务器和其他玩家。
- 优势:低延迟、高效率。
5.WebSocket 在 Java 中的实现与支持工具
WebSocket 核心支持
javax.websocket
- Java 官方提供的标准 API,用于实现 WebSocket 协议。
- 特点:
- 轻量级,无需额外框架。
- 提供服务端和客户端的连接管理、消息处理等核心功能。
- 适用场景:
- 简单的实时通信,如聊天室、通知推送。
- 需要手动控制 WebSocket 会话的场景。
Spring WebSocket
- 基于
javax.websocket
的增强实现,与 Spring Boot 无缝集成。 - 特点:
- 提供消息转换(如 JSON 支持)、会话管理等功能。
- 支持回退机制(通过 SockJS 自动降级到长轮询)。
- 适用场景:
- 使用 Spring Boot 的项目。
- 需要快速开发或整合 Spring Security 的场景。
高级支持工具
Netty
- 高性能网络通信框架,支持多种协议,包括 WebSocket。
- 特点:
- 高并发、低延迟。
- 提供帧级别的控制,适合复杂场景。
- 适用场景:
- 高并发需求,如在线游戏、实时行情推送。
- 需要多协议支持(如同时处理 TCP、HTTP、WebSocket)。
Socket.IO
- 基于 WebSocket 的高级封装,提供事件驱动编程和降级支持。
- 特点:
- 自动处理 WebSocket 不可用的降级(如长轮询)。
- 简化消息传递,支持事件驱动模型。
- 适用场景:
- 跨浏览器兼容性要求高。
- 快速开发实时应用,如聊天系统、通知推送。
工具/框架 | 特点 | 适用场景 |
---|---|---|
javax.websocket | 轻量级,提供基础功能。 | 简单的 WebSocket 应用,手动控制连接的场景。 |
Spring WebSocket | 增强版,与 Spring Boot 集成,支持消息转换和回退机制。 | 基于 Spring 的项目,快速集成复杂功能。 |
Netty | 高性能网络框架,支持多协议和复杂场景。 | 高并发需求或需要多协议支持的场景。 |
Socket.IO | 高级封装,自动降级和事件驱动编程,跨平台兼容性强。 | 需要兼容旧浏览器或快速开发实时应用的场景。 |
总结:
- 如果需要轻量实现,直接使用
javax.websocket
。 - 如果是 Spring Boot 项目,优先选择 Spring WebSocket。
- 对于高性能或复杂场景,选择 Netty。
- 如果需要快速开发、兼容性要求高,使用 Socket.IO。
6.在 Java 中使用 javax.websocket
实现实时通信
1. WebSocket 的使用步骤
在 Java 中使用 javax.websocket
实现实时通信时,需要完成以下步骤:
-
引入必要的依赖
WebSocket 的标准 API 是 Java EE 的一部分。需要引入javax.websocket
和 WebSocket 的实现(如Tyrus
)。 -
创建 WebSocket 服务端
使用@ServerEndpoint
注解定义 WebSocket 端点,处理客户端的连接、消息和断开事件。 -
配置 WebSocket 服务端
在 Spring Boot 中注册 WebSocket 端点,使其能与 Web 应用程序协同运行。 -
创建 WebSocket 客户端(可选)
使用@ClientEndpoint
注解定义客户端端点,用于连接服务端并实现双向通信。 -
启动服务并进行通信
测试服务端与客户端之间的实时消息交换。
2. 引入依赖
在 Spring Boot 项目中,引入以下依赖:
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>tyrus-server</artifactId>
<version>1.17</version>
</dependency>
javax.websocket-api
提供 WebSocket API 接口。tyrus-server
是 WebSocket 的实现库,用于支持运行。
3. 创建 WebSocket 服务端
在 Java 中,使用 @ServerEndpoint
注解定义服务端。
完整代码示例
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
@ServerEndpoint("/websocket")
public class WebSocketServer {
// 存储所有客户端会话
private static final CopyOnWriteArraySet<WebSocketServer> clients = new CopyOnWriteArraySet<>();
// 当前会话
private Session session;
// 当客户端连接成功时触发
@OnOpen
public void onOpen(Session session) {
this.session = session; // 保存当前会话
clients.add(this); // 添加到客户端集合
System.out.println("新的连接已建立,当前连接数:" + clients.size());
sendMessage("欢迎加入 WebSocket 通信!");
}
// 当收到客户端消息时触发
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("收到客户端消息:" + message);
broadcast("服务器收到消息:" + message); // 广播给所有客户端
}
// 当连接关闭时触发
@OnClose
public void onClose(Session session) {
clients.remove(this); // 从客户端集合中移除
System.out.println("连接已关闭,当前连接数:" + clients.size());
}
// 当发生错误时触发
@OnError
public void onError(Session session, Throwable error) {
System.err.println("发生错误:" + error.getMessage());
}
// 向当前客户端发送消息
private void sendMessage(String message) {
try {
this.session.getBasicRemote().sendText(message); // 发送文本消息
} catch (IOException e) {
e.printStackTrace();
}
}
// 向所有客户端广播消息
private void broadcast(String message) {
for (WebSocketServer client : clients) {
try {
client.session.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
代码详解
-
类注解 @ServerEndpoint
- 指定 WebSocket 服务端的路径为
/websocket
。 - 客户端通过
ws://localhost:8080/websocket
连接服务端。
- 指定 WebSocket 服务端的路径为
-
@OnOpen
方法- 在客户端连接成功时调用。
- 参数
Session
:表示与客户端的会话,用于发送消息或获取连接信息。 - 将当前会话保存到
clients
集合中,便于广播消息。
-
@OnMessage
方法- 在收到客户端消息时调用。
- 参数
message
:客户端发送的消息。 - 将消息打印到控制台,并广播给所有已连接的客户端。
-
@OnClose
方法- 在客户端关闭连接时调用。
- 从
clients
集合中移除当前会话。
-
@OnError
方法- 在通信过程中发生异常时触发。
- 可以记录日志或进行异常处理。
-
sendMessage(String message)
方法- 使用
Session
的getBasicRemote().sendText()
方法发送消息到当前客户端。
- 使用
-
broadcast(String message)
方法- 遍历
clients
集合,将消息广播给所有客户端。
- 遍历
4. 配置 WebSocket 服务端
将 WebSocket 服务注册到 Spring Boot 项目中。
实现代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.websocket.server.ServerEndpointConfig;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointConfig.Configurator websocketConfigurator() {
return new ServerEndpointConfig.Configurator();
}
}
步骤说明:
- 配置类使用
@Configuration
注解。 - 将
@ServerEndpoint
标注的类注册为 WebSocket 服务。
5. 创建 WebSocket 客户端
使用 javax.websocket
提供的 API 创建客户端,用于连接服务端并与其通信。
完整代码示例
import javax.websocket.*;
import java.net.URI;
@ClientEndpoint
public class WebSocketClient {
@OnOpen
public void onOpen(Session session) {
System.out.println("客户端成功连接到服务端");
try {
session.getBasicRemote().sendText("Hello, WebSocket Server!");
} catch (IOException e) {
e.printStackTrace();
}
}
@OnMessage
public void onMessage(String message) {
System.out.println("收到服务端消息:" + message);
}
@OnClose
public void onClose() {
System.out.println("客户端连接已关闭");
}
@OnError
public void onError(Throwable error) {
System.err.println("客户端发生错误:" + error.getMessage());
}
public static void main(String[] args) {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
String uri = "ws://localhost:8080/websocket";
try {
container.connectToServer(WebSocketClient.class, URI.create(uri));
} catch (Exception e) {
e.printStackTrace();
}
}
}
代码详解
-
类注解 @ClientEndpoint
- 指定该类为 WebSocket 客户端。
-
@OnOpen
方法- 在客户端成功连接到服务端时调用。
- 使用
Session
对象的getBasicRemote().sendText()
方法向服务端发送消息。
-
@OnMessage
方法- 在客户端收到服务端消息时调用。
- 参数
message
:服务端发送的消息。
-
@OnClose
方法- 在客户端与服务端断开连接时调用。
-
@OnError
方法- 在通信过程中发生异常时触发。
-
main
方法- 使用
WebSocketContainer
创建客户端连接,连接地址为ws://localhost:8080/websocket
。
- 使用
原文地址:https://blog.csdn.net/m0_73837751/article/details/144033129
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!