详解WebSocket

news2025/1/16 13:54:11

目录

1.WebSocket是什么?

2.WebSocket的通信过程

3.WebSocket的报文结构

4.JAVA中的WebSocket


1.WebSocket是什么?

在传统的BS体系中,请求响应一直是单向的,服务器一直扮演的”被动“的角色,浏览器发起请求去访问服务器,服务器才会返回响应。这种单向的模式让实时通信、消息推送一类的场景,实现起来成本巨大。

HTML5里面提出了WebSocket标准,目的就是让服务器具有”主动“的能力,能由服务器向浏览器主动推送东西。WebSocket 是一种基于 TCP 协议的应用层协议,它允许客户端和服务器之间建立持久连接,实现实时通信和推送功能,其和HTTP属于并列的关系:

 

2.WebSocket的通信过程

WebSocket的通信分为两个阶段:

  • 握手阶段

  • 数据交换阶段

握手阶段:

  • 客户端通过 HTTP 请求发起握手请求,请求头包含一些特殊的字段,如pgrade: websocket和 Connection: Upgrade,以及其他的 WebSocket 相关字段。

  • 服务器响应握手:服务器收到客户端的 WebSocket 握手请求后,进行协议升级,将 HTTP 连接升级为 WebSocket 连接。服务器返回一个 WebSocket 握手响应,响应头中包含特殊字段,如 Upgrade: websocketConnection: Upgrade,以及其他的 WebSocket 相关字段。

  • 连接建立:一旦客户端收到服务器的 WebSocket 握手响应,WebSocket 连接就建立成功,现在客户端和服务器都可以发送和接收 WebSocket 消息了。

数据交换阶段:

  • 双向数据交换:WebSocket 连接建立后,客户端和服务器可以通过 WebSocket 会话进行双向的数据交换。任何一方都可以随时发送消息给对方,而不需要事先发出请求。这使得客户端和服务器能够实时交流和传输数据。

  • 数据帧:WebSocket 使用数据帧(Frame)来传输数据。数据帧是 WebSocket 数据的最小传输单元。数据帧可以被分割成多个片段来传输更大的数据。数据帧中包含了有效载荷(Payload)和一些控制信息,例如标识消息类型、是否为最后一个片段等。

  • 心跳检测:WebSocket 连接建立后,客户端和服务器可以通过发送心跳数据帧来维持连接。心跳检测可以确保连接的持久性,如果在一段时间内没有收到心跳响应,可以判断连接已断开。

3.WebSocket的报文结构

websocket的报文=结束标志位 + 操作码 + 帧长度 + 掩码

  • 第一位“FIN”:相当于 HTTP/2 里的“END_STREAM”,表示数据发送完毕。一个消息可以拆成多个帧,接收方看到“FIN”后,就可以把前面的帧拼起来,组成完整的消息。

  • “FIN”后面的三个位是保留位,目前没有任何意义,但必须是 0。

  • “Opcode”,操作码:其实就是帧类型,比如 1 表示帧内容是纯文本,2 表示帧内容是二进制数据,8 是关闭连接,9 和 10 分别是连接保活的 PING 和 PONG。

  • 掩码标志位“MASK”:表示帧内容是否使用异或操作(xor)做简单的加密。目前的 WebSocket 标准规定,客户端发送数据必须使用掩码,而服务器发送则必须不使用掩码。

  • “Payload len”:表示帧内容的长度。它是另一种变长编码,最少 7 位,最多是 7+64 位,也就是额外增加 8 个字节,所以一个 WebSocket 帧最大是 2^64。

  • “Masking-key”:掩码密钥,它是由上面的标志位“MASK”决定的,如果使用掩码就是 4 个字节的随机数,否则就不存在。

4.JAVA中的WebSocket

WebSocket作为一个HTML5标准,也就是前端提出的标准,后端服务器需要支持这种标准,也就是能准确解析WebSocket的数据包,按照约定的标准来办事儿,才能使用WebSocket。

Java 的 Servlet 3.1 规范中包含了对 WebSocket 的支持,也就是说支持Servlet 3.1的Web Server就支持WebSocket。实际开发中常用的tomcat、netty都支持websocket。

这里给出Spring Boot中使用WebSocket的demo。其底层是用的TomCat支持的WebSocket标准。

依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

websocket处理器:

每一个 WebSocket 连接对应一个 WebSocketSession。当客户端通过 WebSocket 建立连接时,服务器会为每个连接创建一个 WebSocketSession 对象,用于表示该连接的会话信息。

处理器用于处理WebSocketSession。

import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;

@Component
public class MyWebSocketHandler implements WebSocketHandler {

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.out.println("WebSocket 连接建立:" + session.getId());
    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        String payload = message.getPayload().toString();
        System.out.println("接收到消息:" + payload);
        session.sendMessage(new TextMessage("服务器收到消息:" + payload));
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        System.err.println("WebSocket 传输错误:" + session.getId());
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        System.out.println("WebSocket 连接关闭:" + session.getId());
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
}

配置、注册websocket处理器:

import org.springframework.beans.factory.annotation.Autowired;
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 {

    @Autowired
    private MyWebSocketHandler webSocketHandler;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(webSocketHandler, "/ws").setAllowedOrigins("*");
    }
}

前端代码示例:

<!DOCTYPE html>
<html>
<head>
    <title>WebSocket Test</title>
</head>
<body>
    <button onclick="sendMessage()">发送消息</button>
    <div id="messageBox"></div>

    <script>
        const ws = new WebSocket('ws://localhost:8080/ws');

        ws.onopen = function(event) {
            console.log('WebSocket 已连接');
        };

        ws.onmessage = function(event) {
            document.getElementById('messageBox').innerHTML += '<p>' + event.data + '</p>';
        };

        ws.onclose = function(event) {
            console.log('WebSocket 已关闭');
        };

        function sendMessage() {
            const message = prompt('请输入要发送的消息:');
            ws.send(message);
        }
    </script>
</body>
</html>

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

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

相关文章

FFmpeg常见命令行(一):FFmpeg工具使用基础

前言 在Android音视频开发中&#xff0c;网上知识点过于零碎&#xff0c;自学起来难度非常大&#xff0c;不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》。本文是Android音视频任务列表的其中一个&#xff0c; 对应的要学习的内容是&#xff1a;FFmpe…

Windows下安装sqlmap及应用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Windows下安装sqlmap前提下载安装创建快捷方式修改属性 使用验证安装成功 使用GET猜解是否能注入查找数据库猜解表(假如通过(2)得到了web1这个数据库)根据猜解的表进…

uniApp 插件 Fvv-UniSerialPort 使用实例

接上一篇 uniApp 对接安卓平板刷卡器, 读取串口数据 , 本文将详细介绍如何使用插件读取到串口数据 原理 通过uniApp 插件读取设备串口数据, 解析后供业务使用; 步骤 创建uniApp 项目;添加插件 安卓串口通信 Fvv-UniSerialPort 安卓串口通信 Fvv-UniSerialPort - DCloud 插件…

简单高效的npm地址源管理器

Note: 这个库的灵感来自于使用 nrm 时只切换 npm 的问题 您可以使用此库来帮助npm、cnpm、yarn和pnpm快速切换下载地址源。此外&#xff0c;你还可以指定单个或多个地址源进行切换。 这个库将为您省去切换地址源的许多麻烦&#xff01; 1、为什么使用 但你想要简单快速地切换…

宝塔Linux面板Java项目部署域名访问 (SpringBoot项目)

1. 域名解析 (阿里云) 我的域名是阿里云, 服务器是腾讯云 2. SSL证书申请 (阿里云) 3. 证书签发成功 (阿里云) 4. 下载Nginx证书 (阿里云) 5. 解压获取 .key 和 .pem 文件 6. 添加域名 (腾讯云) 7. 添加域名 (宝塔面板) 8. SSL (宝塔面板) 9. SSL 添加成功 10. 域名访问项目 (成…

【AI底层逻辑】——篇章6:人工神经网络(深度学习算法)

目录 引入 一、深度学习算法 1、人工神经网络结构 2、卷积神经网络 3、循环神经网络&#xff1a;模拟记忆 ①循环神经网络 ②长短时记忆网络&#xff08;LSTM&#xff09; 4、强化学习 ①强化学习的控制论 ②强化学习的反馈机制 ③马尔可夫决策过程 ④强化学习的重…

开始学习 Kafka,一文掌握基本概念|Kafka 系列 一

如果你还不了解 Kafka&#xff0c;或者也打算深入探索、系统学习&#xff0c;那么欢迎有同样目标的小伙伴可以加群交流&#xff0c;让学习之路不再孤独。 一个人可能走的很快&#xff0c;但是一群人会走的更远。&#xff08;后台回复&#xff1a;加群&#xff09; 点击上方“后…

如何做好主机安全防护

当今数字化时代&#xff0c;网络安全威胁和风险日益突出&#xff0c;已成为企业面临的重大安全挑战。网络攻击者不断尝试利用各种技术和手段对企业网络资源进行探测和攻击&#xff0c;如&#xff1a;利用漏洞、木马、钓鱼、勒索等方式窃取数据、破坏系统、篡改信息。因此&#…

Semantic Kernel 入门系列:Semantic Function

如果把提示词也算作一种代码的话&#xff0c;那么语义技能所带来的将会是全新编程方式&#xff0c;自然语言编程。 通常情况下一段prompt就可以构成一个Semantic Function&#xff0c;如此这般简单&#xff0c;如果我们提前可以组织好一段段prompt的管理方式&#xff0c;甚至可…

软考论文如何得高分?

软考论文如何才能得高分&#xff1f;这是最近很多同事咨询我的问题&#xff0c;最近几天我也反思了一下为什么我的论文可以取得高分&#xff0c;对比了一下网络上45-55分的论文之后&#xff0c;总结如下&#xff1a; 1.子题目的要求一定要重点全面的回应 2. 要有过渡段-理论结…

如何分辨几类网线 如何制作网线的工作笔记

如何分辨几类网线 方法一. 可以通过查看网线的皮胶套上的数字进行判断 方法二. 1、六类网线和五类网线的内部结构不同&#xff0c;六类网线内部结构增加了十字骨架&#xff0c;将双绞线的四对线缆分别置于十字骨架的四个凹槽内&#xff0c;电缆中央的十字骨架随长度的变化而…

spark history网络流量占用高问题记录

生产环境遇到一台机器网络流量占用高告警 由于监控只有机器总的网络流量&#xff0c;没有具体进程的 于是只能登陆服务器&#xff0c;安装nethogs&#xff1a;yum install nethogs 然后执行nethogs命令查看进程流量 观察到主要是spark history server这个进程占用流量高(最高…

Kafka3.0.0版本——生产者如何提高吞吐量

目录 一、生产者提高吞吐量参数设置二、产者提高吞吐量代码示例 一、生产者提高吞吐量参数设置 batch.size&#xff1a;设置批次大小&#xff0c;默认16klinger.ms&#xff1a;设置等待时间&#xff0c;修改为5-100msbuffer.memory&#xff1a;设置缓冲区大小&#xff0c; 默认…

数字孪生电力:让电力智能化

随着科技的飞速发展&#xff0c;电力行业的智能化进程不断推进。智慧电力可以实现系统管理和能源分配的优化&#xff0c;实现电力行业的降本增效。以下主要介绍易知微科技有限公司为湖南国网建设的电力项目案例。 一、行业背景 1.1 政策背景 2014年12月获国务院常务会议原则通过…

抄写Linux源码(Day3:启动南大OS)

我们可以尝试启动南大OS&#xff0c;接着阅读南大OS源码&#xff0c;看看 JYY/YZH 构建主引导扇区的手段 &#xff08;注意&#xff1a;我使用的是南大2023年的 OS 实验代码&#xff09; https://jyywiki.cn/OS/2023/labs/Labs 首先&#xff0c;根据 JYY 的文档&#xff0c;…

jenkins gitlab多分支构建发布

内容背景介绍 这个是新手教程,普及概念为主 公司现在还使用单分支发布测试环境和生产,多人协同开发同一个项目导致测试环境占用等待等情况 测试环境占用等待问题 测试环境代码直接合并到 master,容易导致误发布到生产的情况 避免多版本同时发布测试不完善的情况出现 中间件…

汇川伺服驱动器整理

额定电压&#xff08;V&#xff09;功率&#xff08;KW&#xff09;额定输入电流&#xff08;A&#xff09;系数乘系数电流&#xff08;A&#xff09;推荐断路器电流&#xff08;A&#xff09;单相220V0.22.31.53.4540.441.5660.757.91.511.851619.61.514.4161.512.81.519.220三…

【100天精通python】Day24:python 迭代器,生成器,修饰器应用详解与示例

目录 专栏导读 1 迭代器&#xff0c;生成器&#xff0c;修饰器概述 1.1 概述 1.2 应用场景 2 语法与示例 2.1 迭代器 2.2 生成器 2.3 修饰器 3 综合应用案例 专栏导读 专栏订阅地址&#xff1a;https://blog.csdn.net/qq_35831906/category_12375510.html 1 迭代器&a…

助力工业物联网,工业大数据之ST层的设计【二十五】

文章目录 04&#xff1a;ST层的设计05&#xff1a;服务域&#xff1a;工单主题分析06&#xff1a;服务域&#xff1a;工单主题实现 04&#xff1a;ST层的设计 目标&#xff1a;掌握ST层的设计 路径 step1&#xff1a;功能step2&#xff1a;来源step3&#xff1a;需求 实施 功…

HTML之表单标签

目录 表单标签 Form表单 定义&#xff1a; 基本语法结构&#xff1a; form属性&#xff1a; enctyoe属性 fieldeset标签 fieldeset属性 legend标签 label标签 优势 label属性 input标签 input属性 input标签中的type属性 text text输入框有以下配套属性 searc bu…