WebSocket 详解--spring boot简单使用案例

news2024/12/25 9:13:10

一、什么是WebSocket

WebSocket 是一种网络通信协议,专为在单个 TCP 连接上进行全双工通信而设计。WebSocket 允许客户端和服务器之间的消息能够实时双向传输。这与传统的 HTTP 请求-响应模式有很大的不同。

二、WebSocket 的关键特性

  • 双向通信:WebSocket 提供了双向通信通道。客户端和服务器可以随时向对方发送消息,而无需客户端发起请求。

  • 持久连接:一旦 WebSocket 连接建立,连接将保持打开状态,直到客户端或服务器显式关闭它。这样避免了频繁的 HTTP 请求开销。

  • 低延迟:由于连接保持打开状态,WebSocket 消息的传输延迟非常低,非常适合需要快速响应的应用,如在线游戏、实时聊天等。

  • 轻量协议:WebSocket 协议头部相对较小,减少了数据传输的开销。

三、WebSocket 工作原理

  • 握手:WebSocket 连接始于 HTTP 请求。客户端发出一个带有特殊头部的 HTTP 请求,要求升级到 WebSocket 协议。服务器同意后,通过 HTTP 101 状态码响应,表示协议切换。

  • 数据传输:握手完成后,客户端和服务器之间的通信切换到 WebSocket 协议。两者可以在这条连接上随时发送文本或二进制消息。

  • 连接关闭:连接可以由客户端或服务器主动关闭,通过发送关闭消息并随后关闭 TCP 连接。

四、WebSocket 应用场景

  1. 实时聊天应用:如在线客服、社交网络聊天。
  2. 在线游戏:需要低延迟实时通信的多人游戏。
  3. 实时数据流:如股票行情、体育比分更新。
  4. 协同编辑:如 Google Docs 这样的实时文档编辑工具。
  5. 物联网(IoT)设备:需要与服务器持续通信的智能设备。

WebSocket 的优势在于其双向通信能力和低延迟,是需要实时数据更新的应用的不二选择。

五、WebSocket简单使用案例——java为例

1、为了方便部署,直接创建一个spring boot项目

首先,使用 Spring Initializr 创建一个新的 Spring Boot 项目。你可以访问 Spring Initializr 或者在 IntelliJ IDEA 中创建一个新项目。

选择的依赖项

  • Spring Web
  • Spring Boot Starter WebSocket

下载项目并解压到你的工作目录中。

2. 编写 WebSocket 服务器端点

2.1 创建 WebSocket 配置类

src/main/java/com/example/demo 下创建一个配置类 WebSocketConfig.java

package com.example.demo;

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
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(new MyWebSocketHandler(), "/websocket")
                .setAllowedOrigins("*");
    }
}
2.2 创建 WebSocket 处理器

在同一包下创建一个处理器类 MyWebSocketHandler.java

package com.example.demo;

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 {

    private static Set<WebSocketSession> sessions = 
        Collections.synchronizedSet(new HashSet<>());

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        sessions.add(session);
    }

    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        for (WebSocketSession webSocketSession : sessions) {
            if (webSocketSession.isOpen() && !session.getId().equals(webSocketSession.getId())) {
                webSocketSession.sendMessage(new TextMessage(message.getPayload()));
            }
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        sessions.remove(session);
    }
}

3. 创建 WebSocket 客户端

为了测试 WebSocket,我们可以创建一个简单的 HTML 文件和 JavaScript 客户端。

src/main/resources/static 下创建一个新的 HTML 文件 index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocket Test</title>
</head>
<body>
    <h1>WebSocket Test</h1>
    <input type="text" id="messageInput" placeholder="Enter message">
    <button onclick="sendMessage()">Send</button>
    <ul id="messages"></ul>

    <script>
        let websocket = new WebSocket("ws://localhost:8080/websocket");

        websocket.onopen = function(event) {
            console.log("Connected to WebSocket");
        };

        websocket.onmessage = function(event) {
            let messages = document.getElementById("messages");
            let message = document.createElement("li");
            message.textContent = event.data;
            messages.appendChild(message);
        };

        websocket.onclose = function(event) {
            console.log("Disconnected from WebSocket");
        };

        function sendMessage() {
            let input = document.getElementById("messageInput");
            websocket.send(input.value);
            input.value = '';
        }
    </script>
</body>
</html>

4. 运行 Spring Boot 应用程序

打开你的 IDE(如 IntelliJ IDEA),加载项目并运行 Spring Boot 应用程序。

你可以通过运行 DemoApplication.java 主类来启动应用程序:

package com.example.demo;

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

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

5. 测试 WebSocket

启动应用程序后,打开浏览器并访问 http://localhost:8080。你应该看到一个简单的页面,允许你输入消息并发送。消息将通过 WebSocket 发送到服务器,并广播到所有连接的客户端。

这是一个使用 Spring Boot 和注解配置的 WebSocket 完整示例。这个示例展示了如何使用注解简化 WebSocket 的配置和处理。你可以根据需要进一步扩展和定制这个项目。

6、效果展示

7、注解的写法

直接使用注解包括 @OnOpen, @OnMessage, @OnClose, @OnError等去配置websocket

创建一个配置类 WebSocketConfig.java:

package com.example.demo;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {

    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

在同一包下创建 WebSocket 端点类 WebSocketServer.java

package com.example.demo;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

@ServerEndpoint("/websocket")
public class WebSocketServer {

    private static Set<Session> clients = Collections.synchronizedSet(new HashSet<>());

    @OnOpen
    public void onOpen(Session session) {
        clients.add(session);
        System.out.println("New connection with client id: " + session.getId());
    }

    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        System.out.println("New message from client id: " + session.getId() + ": " + message);
        for (Session client : clients) {
            if (!client.getId().equals(session.getId())) {
                client.getBasicRemote().sendText(message);
            }
        }
    }

    @OnClose
    public void onClose(Session session) {
        clients.remove(session);
        System.out.println("Connection closed with client id: " + session.getId());
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        System.out.println("Error from client id: " + session.getId());
        throwable.printStackTrace();
    }
}

其他地方和上面的一样。

六、实际开发可能需要考虑的相关问题

1、处理客户端断网的策略。

  • 心跳检测:定期发送心跳消息以确保连接的有效性。
  • 超时处理:在特定时间内未收到客户端的消息或心跳回应时关闭连接。
  • 异常处理:捕获并处理连接异常,如断网错误。

2、连接管理

  • 连接断开和重连:客户端可能会由于网络波动、服务器重启等原因导致连接断开。需要实现自动重连机制。
    • 解决方案:客户端实现自动重连,服务器端实现连接状态的监控和重连处理。
  • 连接数量限制:服务器可能会面临大量的并发连接,需要管理连接的生命周期。
    • 解决方案:使用连接池、限制单个用户的最大连接数、负载均衡。

3、数据传输

  • 消息顺序:WebSocket 是全双工通信,消息可能会乱序到达。

    • 解决方案:在消息中添加序列号,客户端根据序列号重排消息。
  • 消息大小:某些应用可能需要传输大数据,WebSocket 本身对消息大小有一定限制。

    • 解决方案:将大消息分割成小块发送,在客户端重新组装。

4、安全性

  • 数据加密:WebSocket 传输的数据可以被中间人截获。

    • 解决方案:使用 wss:// 协议(基于 TLS 加密的 WebSocket)确保传输安全。
  • 身份验证和授权:需要确保只有经过认证和授权的客户端才能建立 WebSocket 连接。

    • 解决方案:在握手阶段进行身份验证,使用 JWT 或其他令牌机制。
  • 跨站脚本攻击 (XSS):WebSocket 可能成为 XSS 攻击的目标。

    • 解决方案:在服务器端验证和过滤输入数据,确保数据格式和内容安全。

5、性能优化

  • 延迟:需要尽量减少消息传输的延迟。

    • 解决方案:优化网络路径、使用更快的服务器、减少数据量。
  • 带宽消耗:频繁的消息传输会消耗大量带宽。

    • 解决方案:压缩消息、优化数据结构。

6、服务器架构

  • 扩展性:需要确保 WebSocket 服务器能处理大量并发连接。

    • 解决方案:使用集群和负载均衡,将连接分配到多个服务器上。
  • 高可用性:需要确保服务器在出现故障时能迅速恢复。

    • 解决方案:使用容错和故障转移机制,配置多个冗余服务器。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1821044.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vi/vim使用命令

你是否在编辑文件时以为键盘坏了&#xff0c;为什么不能删除呢&#xff0c;为什么不能敲代码呢&#xff0c;等你初识vi&#xff0c;会觉得这个东西为什么设计得这么难用&#xff0c;这篇教程带你熟练得用上这款经典的工具 Vi 是在 Unix 系统上广泛使用的编辑器&#xff0c;Vim …

java原子变量

在Java中&#xff0c;原子变量是一种特殊的变量&#xff0c;它们提供了一种不需要显式加锁的情况下进行线程安全的操作。Java.util.concurrent.atomic包提供了原子变量类&#xff0c;如AtomicInteger&#xff0c;AtomicLong等&#xff0c;它们利用底层硬件的原子操作来保证线程…

VRChat 2024年裁员原因与背景深度分析

VRChat&#xff0c;作为2022年元宇宙/VR社交领域的巨头&#xff0c;近期在2024年宣布裁员计划&#xff0c;其背后原因和背景值得业界尤其是仍在纯元宇宙虚拟空间创业的同仁们重点关注。 一、创始人决策失误 根据CEO的邮件披露&#xff0c;VRChat的创始人因缺乏经验和过度自信…

HTTP 概述

HTTP 概述 HTTP 是一种用于获取资源&#xff08;如 HTML 文档&#xff09;的协议。 它是 Web 上任何数据交换的基础&#xff0c;它是一种客户端-服务器协议&#xff0c;这意味着请求由接收方&#xff08;通常是 Web 浏览器&#xff09;发起。 一个完整的文档是从获取的不同子文…

10 SpringBoot 静态资源访问

我们在开发Web项目的时候&#xff0c;往往会有很多静态资源&#xff0c;如html、图片、css等。那如何向前端返回静态资源呢&#xff1f; 以前做过web开发的同学应该知道&#xff0c;我们以前创建的web工程下面会有一个webapp的目录&#xff0c;我们只要把静态资源放在该目录下…

N32G45XVL-STB之移植LVGL(8.4.0)

目录 概述 1 系统软硬件 1.1 软件版本信息 1.2 ST7796-LCD 1.3 MCU IO与LCD PIN对应关系 2 认识LVGL 2.1 LVGL官网 2.2 下载V8.4.0 3 移植LVGL 3.1 硬件驱动实现 3.2 添加LVGL库文件 3.3 移植和硬件相关的代码 3.3.1 驱动接口相关文件介绍 3.3.2 重新接口函数 3…

Lecture3——线性最优化(Linear Optimization)

一&#xff0c;本文重点 线性最优化&#xff08;LP&#xff09;和标准线性最优化&#xff08;Standard LP form&#xff09;的定义如何将LP转换为Standard LP用Python解决LP问题将非线性最优化问题&#xff08;NLP&#xff09;转换为LP 二&#xff0c;定义 1&#xff0c;线性…

Java多线程面试重点-1

0. 什么是并发&#xff1f;什么是并行&#xff1f; 并发&#xff1a;把时间分成一段一段&#xff0c;每个线程轮流抢占时间段。 如果时间段非常短&#xff0c;线程切换非常快&#xff0c;被称为伪并行。并行&#xff1a;多个线程可以同时运行。 并发与并行造成的影响&#xff…

k8s之kubelet证书时间过期升级

1.查看当前证书时间 # kubeadm alpha certs renew kubelet Kubeadm experimental sub-commands kubeadm是一个用于引导Kubernetes集群的工具&#xff0c;它提供了许多命令和子命令来管理集群的一生周期。过去&#xff0c;某些功能被标记为实验性的&#xff0c;并通过kubeadm a…

vue3 前端验证码-删除最后一个,焦点聚焦在前一个值上,并不会删除值

删除最后一个数字&#xff0c;焦点聚焦在前一个值上&#xff0c;并不会删除值 <inputv-for"(box, index) in boxes":key"index"ref"inputRefs":value"box"input"onInputChange(index)"keyup"onKeyDown($event, inde…

WARNING: pip is configured with locations that require TLS/SSL

在pycharm中运行pip下载软件包遇到该问题&#xff1a;WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available 原因&#xff1a;没有安装openssl&#xff1b; 到https://slproweb.com/products/Win32OpenSSL.ht…

u-boot(五) - 启动流程概述

一&#xff0c;XIP设备 一上电&#xff0c;CPU必定从XIP设备得到第1条指令。 XIP设备是指一种可以直接在存储器中执行程序代码的设备&#xff0c;而不需要将代码复制到内存中。XIP的全称是eXecute In Place&#xff0c;即芯片内执行。这类设备包括片内的SRAM、NOR Flash、Boot…

社区论坛圈子软件APP ,提供互动交流、知识共享和专业交流的社交平台。

社区论坛圈子软件APP的开发能够为用户提供一个互动交流的社交平台&#xff0c;促进用户之间的知识分享、交流和互助。本文将突出社区论坛圈子软件APP的前景、作用和特点&#xff0c;以帮助您了解该系统的潜力和优势。 一、前景&#xff1a; 知识共享&#xff1a;社区论坛圈子软…

线程有规律循环打印输出,线程拷贝图片运用

1&#xff1a;线程打印循环&#xff08;保证循环顺序输出&#xff09; 使用互斥锁和条件变量实现&#xff1a; #include <stdio.h>#include <pthread.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <semaphore.h>…

【SAP-ABAP】-权限批导-批量给某个角色导入事务码权限

需求&#xff1a;SAP期初上线的时候&#xff0c;业务顾问经常会遇到批量创建角色和分配角色权限的情况 岗位需求&#xff1a;一般是业务顾问定义权限&#xff0c;BASIS进行后期运维&#xff0c;今天讲两个批导功能&#xff0c;方便期初上线 主要函数&#xff1a;PRGN_READ_ROLE…

群体优化算法----多乌鸦搜寻算法介绍,找多目标函数组解,Pareto前沿

介绍 乌鸦搜寻算法&#xff08;Crow Search Algorithm&#xff0c;CSA&#xff09;是一种新型的群体智能优化算法&#xff0c;其灵感来源于乌鸦的行为特性&#xff0c;尤其是乌鸦在食物搜寻和藏匿过程中的智能行为。乌鸦是一种高度聪明的鸟类&#xff0c;它们展示出复杂的社会…

html实现粘贴excel数据,在页面表格中复制

录入数据时&#xff0c;有时候需要把excel中的数据一条条粘贴到页面中&#xff0c;当数据量过多时&#xff0c;这种操作很令人崩溃。本篇文章实现了从excel复制好多行数据后,可在页面粘贴的功能 具体实现代码 <!DOCTYPE html> <html lang"en"> <head…

自适应巡航控制技术规范(简化版)

自适应巡航控制技术规范(简化版) 1 系统概述2 功能需求3 性能需求4 功能激活条件5 功能抑制条件6 系统局限性1 系统概述 ACC 自适应巡航系统可自动控制纵向跟车距离,减轻驾驶员的工作量,即驾驶员无需频繁的踩制动和油门便可完成部分的驾驶任务,但责任主体仍然是驾驶员,驾…

OrangePi AIpro测评:性能、应用与开发者体验解析

一、OrangePi AIpro介绍 OrangePi AIpro(8T)采用昇腾AI技术路线&#xff0c;具体为4核64位处理器AI处理器&#xff0c;集成图形处理器&#xff0c;支持8TOPS AI算力&#xff0c;拥有8GB/16GB LPDDR4X&#xff0c;可以外接32GB/64GB/128GB/256GB eMMC模块&#xff0c;支持双4K高…

SPI转四串口芯片CH9434的设计

一、CH9434的介绍 CH9434 是一款SPI转四串口转接芯片&#xff0c;提供四组全双工的9线异步串口&#xff0c;用于单片机/嵌入式系统扩展异步串口。CH9434包含四个兼容16C550的异步串口&#xff0c;最高支持4Mbps波特率通讯。最多支持25 路GPIO&#xff0c;提供半双工收发自动切换…