自学内容网 自学内容网

WebSocket

1. 什么是 WebSocket?

WebSocket 是一种网络通信协议,它在单个 TCP 连接上提供全双工通信(Full-Duplex Communication)的能力,允许服务器和客户端之间实时传输数据。

  1. 协议特点

    • 全双工通信:服务器和客户端可以主动发送消息,而不是传统 HTTP 的请求-响应模式。
    • 长连接:建立一次连接后,可以持续使用,直到一方主动关闭。
    • 低延迟:消息通过帧(Frame)发送,减少了传统 HTTP 头信息带来的开销。
    • 高效率:适合实时性要求高的场景。
  2. 工作原理

    • 握手阶段:客户端通过 HTTP 发起 WebSocket 升级请求,服务端返回 101 Switching Protocols,连接升级为 WebSocket 协议。
    • 通信阶段:在连接建立后,数据通过轻量级的帧格式进行传输。
    • 关闭阶段:一方主动发送关闭帧,连接断开。

2. WebSocket 的作用

WebSocket 的主要作用是实现实时通信,即当数据在服务器或客户端发生变化时,可以立即推送到对方,而无需轮询(Polling)或长轮询(Long Polling)。

  1. 实时数据传输

    • WebSocket 可以持续保持连接,无需频繁建立和关闭,适合快速传递实时数据。
  2. 服务器主动推送

    • 服务器可以主动向客户端发送消息,减少客户端对服务器的频繁请求。
  3. 节省带宽和资源

    • 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 实现实时通信时,需要完成以下步骤:

  1. 引入必要的依赖
    WebSocket 的标准 API 是 Java EE 的一部分。需要引入 javax.websocket 和 WebSocket 的实现(如 Tyrus)。

  2. 创建 WebSocket 服务端
    使用 @ServerEndpoint 注解定义 WebSocket 端点,处理客户端的连接、消息和断开事件。

  3. 配置 WebSocket 服务端
    在 Spring Boot 中注册 WebSocket 端点,使其能与 Web 应用程序协同运行。

  4. 创建 WebSocket 客户端(可选)
    使用 @ClientEndpoint 注解定义客户端端点,用于连接服务端并实现双向通信。

  5. 启动服务并进行通信
    测试服务端与客户端之间的实时消息交换。


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 连接服务端。
  • @OnOpen 方法

    • 在客户端连接成功时调用。
    • 参数 Session:表示与客户端的会话,用于发送消息或获取连接信息。
    • 将当前会话保存到 clients 集合中,便于广播消息。
  • @OnMessage 方法

    • 在收到客户端消息时调用。
    • 参数 message:客户端发送的消息。
    • 将消息打印到控制台,并广播给所有已连接的客户端。
  • @OnClose 方法

    • 在客户端关闭连接时调用。
    • clients 集合中移除当前会话。
  • @OnError 方法

    • 在通信过程中发生异常时触发。
    • 可以记录日志或进行异常处理。
  • sendMessage(String message) 方法

    • 使用 SessiongetBasicRemote().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)!