LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

不要再自己去实现websocket了,学会这个让你事半功倍

admin
2025年8月26日 10:16 本文热度 20
很多时候,我们在项目中都有用到websocket的场景,如数据实时更新、实时聊天,实时通知等,下面我将带大家了解什么是websocket,websocket和http的区别。

01
websocket是什么?和http的区别
​        WebSocket 是一种在单个 TCP 连接上实现全双工通信的网络协议,它允许客户端和服务器之间建立持久连接,实现实时双向数据传输。与传统的 HTTP 协议(请求 - 响应模式)相比,WebSocket 最大的优势是服务器可以主动向客户端推送数据,无需客户端频繁轮询,极大提升了实时性和效率。

WebSocket 的核心作用

  1. 实时双向通信
    打破 HTTP “客户端请求→服务器响应” 的单向模式,实现服务器和客户端的 “平等对话”:

    例:聊天应用中,A 发送消息后,服务器可立即将消息推送给 B,无需 B 反复刷新页面。

    • 客户端可以随时向服务器发送消息(如聊天输入、操作指令)。

    • 服务器可以主动向客户端推送数据(如实时通知、状态更新)。

  2. 减少网络开销

    • HTTP 每次通信都需要重新建立连接(三次握手),并携带完整的请求头,开销大。

    • WebSocket 一旦建立连接,会保持持久连接,后续通信只需传输数据本身,无需重复握手和携带冗余头信息,适合高频数据传输(如股票行情、游戏数据)。

  3. 低延迟响应
    避免了 HTTP 轮询(客户端定时发送请求)带来的延迟和资源浪费:

    • 轮询方式:客户端每 1 秒发一次请求,即使没有新数据也要消耗资源,且最新数据可能延迟 1 秒。

    • WebSocket 方式:有新数据时服务器立即推送,延迟通常在毫秒级(如实时监控系统中,设备状态变化可瞬间同步到前端)。

与 HTTP 的对比

特性
HTTP
WebSocket
通信方式
单向(客户端请求→服务器响应)
双向(客户端↔服务器)
连接方式
短连接(请求后关闭)
长连接(一次建立,持续通信)
服务器主动性
被动响应,不能主动推送
可主动向客户端推送数据
适用场景
页面加载、接口调用等
实时聊天、监控、游戏等

02
websocket的手动实现

自己实现websocket服务需要基于TCP协议处理握手、帧解析和双向通信。

(1)握手阶段

  • 客户端发送 HTTP 请求,包含 Upgrade: websocket 表示要升级协议。

  • 服务器验证 Sec-WebSocket-Key,通过特定算法(SHA-1 + Base64)生成 Sec-WebSocket-Accept 响应,完成握手。

(2)帧解析与构建

  • WebSocket 数据以 “帧” 为单位传输,帧格式包含类型、长度、掩码(客户端发送时)等信息。

  • 解析客户端消息:需要用掩码解密(异或运算)。

  • 构建服务器响应:无需掩码,直接打包文本为帧格式。

(3)广播功能

  • 服务器维护所有客户端连接的 Socket 集合,收到消息后转发给所有在线客户端。

03

注解式的websocket实现


注解式的实现是我们常用的websocket实现,只需要使用@ServerEndpoint注解标记类为websocket的服务端点,客户端就可以使用ws://地址:端口/端点进行连接。

下面是简单的实现

@ServerEndpoint("/chat")public class ChatServer {    // 存储所有在线会话(线程安全的集合)    private static final Set<Session> onlineSessions =         Collections.synchronizedSet(new HashSet<>());    /**     * 客户端连接建立时触发(对应@OnOpen     */    @OnOpen    public void onOpen(Session session) {        // 将新会话加入在线集合        onlineSessions.add(session);        System.out.println("新客户端连接,会话ID:" + session.getId());        broadcast("系统消息:有新用户加入,当前在线:" + onlineSessions.size() + "人");    }    /**     * 客户端断开连接时触发(对应@OnClose     */    @OnClose    public void onClose(Session session) {        // 从在线集合移除会话        onlineSessions.remove(session);        System.out.println("客户端断开,会话ID:" + session.getId());        broadcast("系统消息:有用户离开,当前在线:" + onlineSessions.size() + "人");    }    /**     * 收到客户端消息时触发(对应@OnMessage     */    @OnMessage    public void onMessage(String message, Session session) {        System.out.println("收到消息(" + session.getId() + "):" + message);        // 广播消息给所有在线客户端        broadcast("用户" + session.getId().substring(06) + ":" + message);    }    /**     * 发生错误时触发(对应@OnError     */    @OnError    public void onError(Session session, Throwable error) {        System.err.println("会话错误(" + session.getId() + "):" + error.getMessage());    }    /**     * 广播消息给所有在线客户端     */    private static void broadcast(String message) {        // 遍历所有会话,发送消息        for (Session session : onlineSessions) {            try {                // 发送消息(getBasicRemote()是同步发送,getAsyncRemote()是异步)                session.getBasicRemote().sendText(message);            } catch (IOException e) {                System.err.println("广播失败:" + e.getMessage());            }        }    }
<!--pom引入--><dependency>    <groupId>javax.websocket</groupId>    <artifactId>javax.websocket-api</artifactId>    <version>1.1</version>    <scope>provided</scope> <!-- 容器已内置该API --></dependency>
04
spring websocket实现-SimpMessagingTemplate 

spring 是spring对JSR 356之上的更高封装,简化消息发送,整合spring生态,SimpMessagingTemplate 消息发送更为简便。

SimpMessagingTemplate 会话方式

// 广播给所有订阅 /topic/news 的客户端 messagingTemplate.convertAndSend("/topic/news""新闻内容");  // 发送给指定用户(结合 Spring Security) messagingTemplate.convertAndSendToUser("user123""/queue/msg""私信");

废话不多说,项目代码看一下。简单三步实现。

1.pom引入spring-boot-starter-websocket<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-websocket</artifactId></dependency>2.注入SimpMessagingTemplateprivate final SimpMessagingTemplate websocketTemplate;3.发送消息websocketTemplate.convertAndSend("/topic/device-updates", message);

这种方式有一个问题:一直发送(如前端订阅页面关闭),我需要只有订阅者在线的时候才发送。于是根据spring websocket 做了一个监听

然后再发送消息时,对在线数进行检查

这是后端所需要实现的,前端我们只需要进行订阅就可以了。

前端我们引入两个js

<script src="/static/util/sockjs.min.js"></script>
<script src="/static/util/stomp.min.js"></script>

然后订阅后端的destination

这样整个双向通信我们就完成了。


该文章在 2025/8/29 12:23:03 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved