WebSocket通信学习笔记

news2024/11/10 13:44:56

1 简介

WebSocket是一种全双工通信协议,它允许客户端和服务器之间建立持久化的双向连接,从而在不频繁创建HTTP请求的情况下进行实时数据传输。与传统的HTTP协议相比,WebSocket更适合需要实时数据更新的应用场景,如聊天应用、实时股票行情、在线游戏等。
WebSocket 是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接, 并进行双向数据传输。
WebSocket可以通过wss://前缀实现加密通信,类似于HTTPS。由于WebSocket协议本身没有对数据的加密和身份验证机制,因此在使用时通常结合TLS/SSL进行加密,并通过认证机制确保通信的安全性。

1.1 工作原理

1) 握手阶段

WebSocket连接从客户端发起一个标准的HTTP请求开始,但这个请求的头部包含一些额外的字段,表示客户端希望升级到WebSocket协议。这是一个GET请求,并且包含以下几个重要的头部字段:

  • Upgrade: websocket:表示客户端希望将这个连接升级为WebSocket。
  • Connection: Upgrade:与Upgrade字段配合使用,表明连接类型的变化。
  • Sec-WebSocket-Key:一个由客户端生成的随机的Base64编码的key,服务器将用它来生成一个响应密钥以确认握手。
  • Sec-WebSocket-Version:表示WebSocket协议的版本,通常为13。

2) 服务器响应

如果服务器支持WebSocket,它将回应一个HTTP 101状态码,表示协议切换成功,并且在响应头部包含以下字段:

  • Upgrade: websocket:确认协议升级。
  • Connection: Upgrade:与Upgrade字段配合使用。
  • Sec-WebSocket-Accept:服务器根据客户端提供的Sec-WebSocket-Key,加上一个固定的字符串,然后通过SHA-1加密并进行Base64编码后生成的值。这个值用于确认握手的有效性。

握手完成后,连接正式切换为WebSocket协议,客户端和服务器可以开始通过这个持久连接进行双向通信。

3) 数据帧传输

一旦连接建立,客户端和服务器之间的数据传输以帧的形式进行。WebSocket的数据帧由一个小的头部和可变长度的数据负载组成,帧可以携带文本数据(UTF-8编码的字符串)或二进制数据。WebSocket支持以下几种帧类型:

  • 文本帧:用于传输文本数据。
  • 二进制帧:用于传输二进制数据。
  • 关闭帧:用于表示连接关闭。
  • Ping帧:客户端或服务器发送Ping帧以测试连接的连通性。
  • Pong帧:用于响应Ping帧。

4) 连接关闭

WebSocket连接可以由客户端或服务器任意一方发起关闭。关闭连接时,必须发送一个关闭帧,其中可以包含关闭码和关闭原因。收到关闭帧后,另一方应尽快发送自己的关闭帧并关闭连接。

1.2 WebSocket 优缺点分析

1)优点

  • 低延迟:由于WebSocket连接是持久的,消除了频繁创建和关闭连接的开销,延迟较低,非常适合需要实时数据更新的应用。
  • 全双工通信:与HTTP的请求-响应模式不同,WebSocket支持全双工通信,客户端和服务器可以同时发送和接收消息。
  • 节省带宽:WebSocket在建立连接后没有HTTP协议的头部负载,可以节省带宽。

2) 缺点

  • 复杂性:WebSocket的实现和调试可能比传统的HTTP协议要复杂,尤其是在处理连接状态、网络问题和安全性方面。
  • 不适用于所有应用:对于一些不需要实时通信的应用,WebSocket可能显得过于复杂和不必要。

1.3 适用场景

  • 实时聊天应用:WebSocket可以实现低延迟的消息传递,非常适合实时聊天。
  • 实时推送:如新闻、体育比分、金融市场数据等。
  • 多人在线游戏:需要低延迟的数据同步和通信。
  • 协作编辑工具:如在线文档编辑、代码协作等,WebSocket可以实现实时的内容同步。

对比 HTTP:

  • HTTP适用于大多数Web应用和API场景,其简单的请求-响应模型、无状态特性和广泛的工具支持,使其成为Web开发的标准选择。
  • WebSocket则适合需要实时、双向数据传输的应用场景,如聊天、在线游戏和金融数据推送。虽然实现上更为复杂,但其在特定场景下的性能和效率优势是HTTP无法比拟的。

详细比较:

  • **通信模式:**HTTP 是请求-响应模式,单项且无状态的;WebSocket 是全双工通信,双向且持续连接。
  • **连接管理:**HTTP通常是短连接,每次请求都重新建立连接;WebSocket是长连接,握手后保持连接,适合频繁数据交换。
  • **使用场景:**HTTP适用于网页加载、API调用等不需要实时更新的场景;WebSocket适用于实时聊天、在线游戏等需要低延迟、实时数据更新的应用。

HTTP和WebSocket底层都是TCP连接。

2 Demo 实例

1) 创建 SpringBoot 项目

2) 引入 Maven 依赖

<!--导入websocket依赖-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

3) 导入前端页面

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="UTF-8">
    <title>WebSocket Demo</title>
  </head>
  <body>
    <input id="text" type="text" />
    <button onclick="send()">发送消息</button>
    <button onclick="closeWebSocket()">关闭连接</button>
    <div id="message">
    </div>
  </body>
  <script type="text/javascript">
    var websocket = null;
    var clientId = Math.random().toString(36).substr(2);

    //判断当前浏览器是否支持WebSocket
    if('WebSocket' in window){
      //连接WebSocket节点
      websocket = new WebSocket("ws://localhost:8080/ws/"+clientId);
    }
    else{
      alert('Not support websocket')
    }

    //连接发生错误的回调方法
    websocket.onerror = function(){
      setMessageInnerHTML("error");
    };

    //连接成功建立的回调方法
    websocket.onopen = function(){
      setMessageInnerHTML("连接成功");
    }

    //接收到消息的回调方法
    websocket.onmessage = function(event){
      setMessageInnerHTML(event.data);
    }

    //连接关闭的回调方法
    websocket.onclose = function(){
      setMessageInnerHTML("close");
    }

    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function(){
      websocket.close();
    }

    //将消息显示在网页上
    function setMessageInnerHTML(innerHTML){
      document.getElementById('message').innerHTML += innerHTML + '<br/>';
    }

    //发送消息
    function send(){
      var message = document.getElementById('text').value;
      websocket.send(message);
    }

    //关闭连接
    function closeWebSocket() {
      websocket.close();
    }
  </script>
</html>

4) 编写后端 websocket 服务类

@Component
@ServerEndpoint("/ws/{sid}")
public class WebSocketServer {
    // 存放会话对象
    private static Map<String, Session> sessionMap = new HashMap<>();


    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("sid") String sid) {
        System.out.println("客户端:" + sid + "建立连接");
        sessionMap.put(sid, session);
    }

    /**
     * 收到客户端消息后调用的方法
     */
    @OnMessage
    public void onMessage(String message, @PathParam("sid") String sid) {
        System.out.println("收到来自客户端:" + sid + "的信息:" + message);
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(@PathParam("sid") String sid) {
        System.out.println("连接断开:" + sid);
        sessionMap.remove(sid);
    }

    /**
     * 群发
     */
    public void sendToAllClient(String message) {
        Collection<Session> sessions = sessionMap.values();
        for (Session session : sessions) {
            try {
                // 服务器向客户端发送消息
                session.getBasicRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

5)编写 websocket 配置类

这个配置类的主要作用是启用WebSocket支持。当Spring容器启动时,它会自动扫描所有标记了@ServerEndpoint注解的类,并将它们注册为WebSocket端点,允许客户端通过这些端点进行WebSocket通信。 如果你在Spring Boot项目中使用内置的Web容器(如Tomcat、Jetty等),并且使用WebSocket,则需要这个ServerEndpointExporter来将WebSocket端点自动注册到容器中。

@Configuration
public class WebSocketConfiguration {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

6) 定时任务模拟后端发送给用户端消息

@Component
public class WebSocketTask {
    @Autowired
    private WebSocketServer webSocketServer;

    /**
     * 通过websocket每隔五秒向客户发送信息
     */
    @Scheduled(cron = "0/5 * * * * ?")
    public void sendMessageToClient() {
        webSocketServer.sendToAllClient("这是来自服务端的消息" + DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now()));
    }
}

3 结果展示

前端结果:
除了自己能主动给后端发送信息以外,前段每隔五秒还能收到后端发来的信息。
image.png
后端结果:
服务端自动接收前段发来的信息,同时会在定时任务中,每隔五秒给前端发送一条信息。
image.png
代码获取:https://gitee.com/strivezhangp/java-study-log.git 切换到相关分支即可拉取。

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

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

相关文章

架构师篇-23、工作坊实战应用架构

复习 ADM - 应用架构【AA】 案例实践 - 应用组件 - 核心模块 案例实践 - xx 项目应用关系 课程内应用架构

科研绘图系列:R语言PCoA图(PCoA plot)

介绍 PCoA(主坐标分析,Principal Coordinate Analysis)是一种多维数据的降维技术,它用于探索高维空间中样本之间的关系。PCoA通常用于生态学、遗传学和其他领域的数据分析,以揭示样本或个体之间的相似性或差异性。 PCoA图的作用: 数据降维:PCoA可以将高维数据(如物种…

18046 字母分类统计

### 思路 1. 读取输入的一行字符。 2. 初始化计数器&#xff1a;字母、数字、空格和其它字符的个数。 3. 遍历每个字符&#xff0c;根据其类型更新相应的计数器。 4. 输出计数结果&#xff0c;格式为&#xff1a;字母、数字、空格和其它字符的个数&#xff0c;中间以空格分隔。…

【2024-2025源码+文档+调试讲解】公开课管理系统

摘 要 随着互联网技术的迅猛发展&#xff0c;教育行业也逐渐迎来了一场全新的变革。在线教育平台的崛起为学习者提供了更加便捷灵活的学习方式&#xff0c;而公开课作为其中的一种形式&#xff0c;因其开放性和多样性而备受欢迎。然而&#xff0c;传统的公开课管理方式存在着…

【案例】如何做B端竞品分析?

竞品分析是产品经理的基本功&#xff0c;B端产品经理同样也需要经常做竞品分析。 B端产品的竞品分析难度更大&#xff0c;主要体现在如下几个方面&#xff1a; 1&#xff09;B端产品的信息获取困难 产品试用成本高&#xff0c;不像互联网产品那样可以随时下载体验。 对外公…

【数学分析笔记】第3章第1节 函数极限(1)

3. 函数极限与连续函数 3.1 函数极限 设有一半径为 r r r的圆&#xff0c;角度 x x x用弧度制表示。 红色的弧长为 2 x r 2xr 2xr&#xff0c;蓝色的弦长为 2 r sin ⁡ x 2r\sin x 2rsinx y 弦长 弧长 sin ⁡ x x y\frac{弦长}{弧长}\frac{\sin x}{x} y弧长弦长​xsinx​…

云计算密钥管理的重要性

云计算密钥管理是指对云计算环境中使用的加密密钥进行全生命周期的管理过程&#xff0c;包括密钥的生成、存储、分发、使用、更新和销毁等环节。这一过程对于保障云计算数据的安全性至关重要。以下是对云计算密钥管理的详细阐述&#xff1a; 一、云计算密钥管理的重要性 随着云…

大道至简 以量取胜

这次聊聊网络推广&#xff0c;这种发文章发视频的推广。 厉害的人&#xff0c;选高权重平台&#xff0c;精心打磨雕琢文案&#xff0c;一篇文案引爆流量十万&#xff0c;非常牛逼。 普通人很难做到这样。也许一篇文案&#xff0c;只有几百个浏览。 咱们简化一下&#xff0c;…

创纪录!300亿美元季度营收背后,英伟达的汽车“困局”

作为全球市值最高的上市公司&#xff0c;英伟达的财务数据变化历来是资本市场关注的焦点。不管是数据中心、游戏还是汽车业务&#xff0c;这家GPU巨头的业务进展&#xff0c;一定程度上也代表着不同细分市场的风向变化。 本周&#xff0c;英伟达对外发布最新数据&#xff0c;截…

北京市公共资源交易中心到访隆道调研交流

8月29日下午&#xff0c;北京市公共资源交易中心调研组在党委副书记朱永利带领下莅临隆道公司开展调研。隆道公司总裁吴树贵、总裁助理姚锐和市场总监张晶热情地接待来访的九位调研组成员&#xff0c;双方就招标采购数字化转型实践、人工智能技术研究和应用等话题展开深入交流。…

(免费领源码)java#SSM#mysql黄冈旅游景点服务网站16627-计算机毕业设计项目选题推荐

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对旅游服务等问题&#xff0c;对旅游服务进行…

Android源码编译_内置apk

在开发过程中&#xff0c;有一部分apk&#xff0c;我们是需要出厂内置好的&#xff0c;例如输入法、客户定制app等&#xff0c;这里内置分两种&#xff0c;一种是只内置apk&#xff0c;不含apk源码&#xff0c;一种是包含apk源码。 一、如何将apk内置到系统 1、首先将apk放到…

【网络安全】XSS+OTP绕过+账户接管

未经许可,不得转载。 文章目录 正文XSSOTP绕过账户接管正文 目标:www.example.com XSS 不断寻找可能存在XSS的点位。 终于,在个人资料页面:www.example.com/profile_details.php?userid= ,使用Payload<script>alert(1)</script>,实现XSS: 因此,能够实…

【书生大模型实战营】进阶岛 第4关 InternVL 多模态模型部署微调实践

文章目录 【书生大模型实战营】进阶岛 第4关 InternVL 多模态模型部署微调实践学习任务什么是InternVLInternVL 模型总览Dynamic High ResolutionPixel ShuffleInternVL 部署微调实践准备InternVL模型准备环境激活虚拟环境&#xff08;注意&#xff1a;后续的所有操作都需要在这…

数字化转型下的高效设备管理:构建智能化、精细化管理体系

企业应对日益复杂的设备管理挑战&#xff0c;通过数字化、智能化手段提升设备管理效率与设备可用性&#xff0c;具体体现在以下几个方面&#xff1a; 全面信息化与结构化&#xff1a;系统首先解决了设备信息散乱无序的问题&#xff0c;通过在线建档与台账管理&#xff0c;将设备…

记一次学习--webshell绕过(利用清洗函数)

目录 样本 样本修改 样本 <?php $a array("t", "system"); shuffle($a); $a[0]($_POST[1]); 通过 shuffle 函数打乱数组,然后通过$a[0]取出第一个元素&#xff0c;打乱后第一个元素可能是t也可能是system。然后再进行POST传参进行命令执行。 这里抓…

Ubuntu 安装个人热点

1. 安装必要的软件 首先&#xff0c;我们需要确保有一些工具已经装好&#xff0c;这些工具会帮助我们创建 Wi-Fi 热点。打开终端&#xff0c;输入以下命令来安装这些工具&#xff1a; sudo apt-get install git hostapd iptables dnsmasq 2. 下载并安装 create_ap 我们接下来…

RabbitMQ 02 操作,配置信息

01.介绍启动&#xff0c;关闭 02.环境 2.1 MQ是用Erlang语言写的 2.2 一个RabbitMQ 节点 一个 Erlang节点一个Erlang 程序 &#xff08;RabbitMQ程序&#xff09; 2.3 Erlang节点&#xff1a; 这个是Erlang节点集群状态下&#xff1a; 2.4 启动节点 2.5 查看日志信息 …

【KingbaseES 人大金仓】| Docker 部署 | 详细步骤

文章目录 版本说明准备工作第 1 步:导入 Docker 镜像第 2 步:创建容器相关说明运行容器第 3 步:查看运行状态第 4 步:使用 ksql 访问数据库第 5 步:修改 license第 6 步:修改配置文件【可选】✅ 本文目标:了解 KingbaseES 数据库、了解 KingbaseES 数据库版本、Docker 部…

CNN中的注意力机制综合指南:从理论到Pytorch代码实现

注意力机制已经成为深度学习模型&#xff0c;尤其是卷积神经网络&#xff08;CNN&#xff09;中不可或缺的组成部分。通过使模型能够选择性地关注输入数据中最相关的部分&#xff0c;注意力机制显著提升了CNN在图像分类、目标检测和语义分割等复杂任务中的性能。本文将全面介绍…