网络-WebSocket

news2024/11/15 13:44:37

文章目录

  • 前言
  • 一、WebSocket简介
    • 应用场景
    • 原理
  • 二、使用
    • 心跳监测
    • 广播消息
  • 三、群聊demo
  • 总结


前言

本文主要记录WebSocket的简单介绍和使用,完成群聊的demo


一、WebSocket简介

WebSocket是一种通信协议,它通过单个TCP连接提供全双工的通信通道。
它允许客户端和服务器之间进行实时的双向通信。
与传统的HTTP请求不同,WebSocket建立了客户端和服务器之间的持久连接,从而实现了高效和低延迟的通信。

要建立WebSocket连接,客户端向服务器发送WebSocket握手请求,服务器则以WebSocket握手响应进行回应。
一旦连接建立,客户端和服务器都可以异步地发送消息。

WebSocket采用基于消息的通信模型,消息以帧的形式通过WebSocket连接发送。
这些帧可以是二进制或文本形式,具体取决于应用程序的需求。
该协议还支持消息分片、用于保持连接的ping/pong消息以及用于优雅终止连接的关闭消息等功能。
WebSocket得到了大多数现代Web浏览器的支持,并且可以在服务器端应用程序中使用提供WebSocket功能的库或框架

应用场景

  • 实时性要求高,如:聊天、游戏、数据可视化
  • 需要频繁交换数据,如:实时协作工具、文件管理器
  • 需要推送服务的应用,如:实时数据监控、通知系统
  • 跨平台应用,如:桌面应用、移动端应用

它提供了比长轮询或服务器推送事件(SSE)更高效的替代方案。

原理

  • 握手阶段:客户端发送一个HTTP请求给服务器,请求升级为WebSocket协议。在请求头中包含一些特殊的字段,如UpgradeConnection,表明客户端希望升级到WebSocket协议,这里也可以使用这里也可以使用WebSocket API进行通讯API进行通讯,实际也是发送GET请求带特殊请求头。服务器收到请求后,如果支持WebSocket协议,则返回一个HTTP响应,状态码为101 Switching Protocols,表示升级成功。

101

  • 建立连接:一旦握手成功,客户端和服务器之间建立了一个持久的双向连接。这个连接是基于TCP的,可以实现全双工通信,即客户端和服务器可以同时发送和接收消息。
    数据传输:客户端和服务器可以通过WebSocket连接发送和接收消息。消息以帧的形式进行传输,可以是二进制数据或文本数据。帧包含了一些控制信息,如消息类型、消息长度等。客户端和服务器可以异步地发送和接收消息,实现实时的双向通信。
  • 保持连接:WebSocket连接是持久的,不会像传统的HTTP请求那样每次都需要重新建立连接。为了保持连接的活跃状态,客户端和服务器可以定期发送心跳消息,以确保连接不会断开。
  • 关闭连接:当客户端或服务器希望关闭WebSocket连接时,可以发送一个关闭帧。接收到关闭帧的一方会响应一个关闭帧,然后双方的连接会被正常关闭。

二、使用

  • 创建ws对象
const ws = new WebSocket('ws://localhost:8080');
  • 监听连接成功
ws.onopen = function () {
            console.log('已连接')
        }
  • 发送消息
ws.send('发送的消息')
  • 接收消息
 ws.onmessage = function (e) {
            console.log(e.message)
        }
  • 断开连接
ws.close()
  • 监听断开连接
ws.onclose = function() {
            console.log('WebSocket连接已关闭');
        };
  • 监听连接错误
ws.onerror = function(error) {
            console.error('WebSocket连接发生错误:', error);
        };
  • 事件监听器
    WS是可以添加事件监听器的,如open、message、close、error等与属性效果是一致的。
 ws.addEventListener('open',function (event) {
            console.log('连接成功')
            isConnected = true;
        })
ws.addEventListener('message',(e)=>{
            let li = document.createElement('li')

            let data = JSON.parse(e.data)
            if (data.type == 2){
                li.innerText = data.message
                list.appendChild(li)
            }else {
                console.log(data.message)
            }
        })

心跳监测

socket连接在长时间不使用、网络波动、弱网状况下有可能断开连接,需要进行心跳监测来保证连接存活。在断开连接时,实现重连,在进行心跳消息发送时,客户端需要将心跳监测信息过滤掉。

 let heartInreaval = null
    const heartCheck = () =>{
        // 等于open 发送心跳
        if (socket.readyState === ws.OPEN){
            socket.send(JSON.stringify({
                type:state.HEART,
                message:'心跳检测'
            }))
        }else {
            clearInterval(heartInreaval)
        }
    }
    setInterval(heartCheck,5000)

广播消息

在后端直接使用send发送消息只能针对点对点的,不能将消息发送给全部连接,需要使用clients属性遍历发送,达到广播的效果

 // 广播消息
        wss.clients.forEach((client)=>{
            client.send(JSON.stringify({
                type:state.MESSAGE,
                message:e.toString()
            }))
        })

三、群聊demo

前端:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <ul id="list"></ul>
    <input type="text" id="input">
    <button id="send">发送</button>
    <button id="stop">断开连接</button>
</div>
</body>
<script>
    // 连接状态
    let isConnected = false;
    let input = document.getElementById('input')
    let btn = document.getElementById('send')
    let list = document.getElementById('list')
    let stop = document.getElementById('stop')
    function connectWebSocket() {
        // 创建ws实例
        const ws = new WebSocket('ws://localhost:8080');
        // 监听连接成功
        ws.addEventListener('open',function (event) {
            console.log('连接成功')
            isConnected = true;
        })
        btn.addEventListener('click',function () {
            if (input.value){
                // send发送消息
                ws.send(input.value)
                input.value = ''
            }
        })
        ws.addEventListener('message',(e)=>{
            let li = document.createElement('li')

            let data = JSON.parse(e.data)
            if (data.type == 2){
                li.innerText = data.message
                list.appendChild(li)
            }else {
                console.log(data.message)
            }
        })
        //断开连接
        stop.addEventListener('click',()=>{
            ws.close()
        })
        // ws.onopen = function () {
        //     console.log('已连接')
        // ws.send('发送的消息')
        // ws.onmessage = function (e) {
        //     console.log(e.message)
        // }
        // }
        ws.onclose = function() {
            console.log('WebSocket连接已关闭');
            isConnected = false;
            // 进行重连
            reconnect();
        };

        // 监听WebSocket连接发生错误事件
        ws.onerror = function(error) {
            console.error('WebSocket连接发生错误:', error);
            isConnected = false;
            // 进行重连
            reconnect();
        };
    }
    // 重连函数
    function reconnect() {
        if (!isConnected) {
            console.log('尝试重新连接...');
            setTimeout(connectWebSocket, 5000);
        }
    }
    connectWebSocket()

</script>
</html>

后端:这里使用Node

//安装 ws
const ws =require('ws')
// 创建socket服务
const wss = new ws.Server({port:8080},()=>{
    console.log('socket服务启动成功')
})

//心跳枚举
const state = {
    HEART:1,
    MESSAGE:2
}

// 监听客户端连接
wss.on('connection',(socket)=>{
    //监听客户端消息
    console.log('客户端连接成功')
    socket.on('message',(e)=>{
        console.log(e.toString())
        // 广播消息
        wss.clients.forEach((client)=>{
            client.send(JSON.stringify({
                type:state.MESSAGE,
                message:e.toString()
            }))
        })
    })
    let heartInreaval = null
    const heartCheck = () =>{
        // 等于open 发送心跳
        if (socket.readyState === ws.OPEN){
            socket.send(JSON.stringify({
                type:state.HEART,
                message:'心跳检测'
            }))
        }else {
            clearInterval(heartInreaval)
        }
    }
    setInterval(heartCheck,5000)
})

群聊


总结

WebSocket通过握手阶段建立持久的双向连接,然后通过帧的方式传输数据,实现实时的双向通信。它相比传统的HTTP请求具有更低的延迟和更高的效率,适用于需要实时更新的Web应用程序。

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

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

相关文章

【C#】标准WebService Soap1.1 兼容 ContentType: application/xml

一、问题描述 1.1 ESB平台要求 ContentType&#xff1a;application/xml Soap协议版本&#xff1a;1.1 1.2 提供的 WebService 接口 语言&#xff1a;C# 目标框架&#xff1a;.NetFramework 4.6.1 1.3 Postman 测试结果 HTTP Error 415.0 - Unsupported Media Type 服务器…

计算机竞赛YOLOv7 目标检测网络解读

文章目录 0 前言1 yolov7的整体结构2 关键点 - backbone关键点 - head3 训练4 使用效果5 最后 0 前言 世界变化太快&#xff0c;YOLOv6还没用熟YOLOv7就来了&#xff0c;如果有同学的毕设项目想用上最新的技术&#xff0c;不妨看看学长的这篇文章&#xff0c;学长带大家简单的…

如何为您的 Linux 服务器设置简单的 Grafana 云监控仪表板

Grafana 是一个开源可观察性平台,用于创建可视化数据集的仪表板。您可以使用它方便地监控服务器统计信息,例如 CPU 消耗、网络吞吐量和正常运行时间。 Grafana可以自托管,也可以通过官方Grafana Cloud实例作为 SaaS 解决方案进行访问。在本文中,您将了解如何设置 Grafana …

修炼k8s+flink+hdfs+dlink(四:k8s(一)概念)

一&#xff1a;概念 1. 概述 1.1 kubernetes对象. k8s对象包含俩个嵌套对象字段。 spec&#xff08;规约&#xff09;&#xff1a;期望状态 status&#xff08;状态&#xff09;&#xff1a;当前状态 当创建对象的时候&#xff0c;会按照spec的状态进行创建&#xff0c;如果…

scratch芝麻开门 2023年9月中国电子学会图形化编程 少儿编程 scratch编程等级考试一级真题和答案解析

目录 scratch芝麻开门 一、题目要求 1、准备工作 2、功能实现 二、案例分析

操作系统学习笔记3-同步互斥问题

文章目录 1 同步与互斥逻辑图2、并发性异步性独立性3、临界资源临界区4、同步与互斥 1 同步与互斥逻辑图 2、并发性异步性独立性 3、临界资源临界区 4、同步与互斥

汽车一键启动点火开关按键一键启动按钮型号规格

汽车点火开关/移动管家一键启动按键/汽车改装引擎启动按钮型号&#xff1a;YD828溥款开关 一键启动按钮&#xff08;适用于配套启动主机使用或原车一键启动开关更换&#xff09; 1.适合配套专用板板安装 2.开孔器开孔安装 3.原车钥匙位安装 外观&#xff1a;黑色 按钮上有3种不…

【融合ChatGPT等AI模型】Python-GEE遥感云大数据分析、管理与可视化及多领域案例实践应用

目录 第一章 理论基础 第二章 开发环境搭建 第三章 遥感大数据处理基础与ChatGPT等AI模型交互 第四章 典型案例操作实践 第五章 输入输出及数据资产高效管理 第六章 云端数据论文出版级可视化 更多应用 随着航空、航天、近地空间等多个遥感平台的不断发展&#xff0c;近…

免费的ChatGPT与StableDiffusion AI绘画 二合一 附在线地址

ChatGPT与StableDiffusion 在线地址在文末 介绍 嘿&#xff0c;大家好&#xff01;今天我要给大家介绍一个非常酷炫的技术结合——ChatGPT与StableDiffusion的合作。听起来是不是很有趣&#xff1f;那么&#xff0c;让我们一起来看看这个组合到底能带给我们什么样的奇妙体验…

Go图片文件按照时间戳如何排序

涉及点包括 文件创建;时间控制器;自建封装包以及方法; 模板渲染;路由配置;不同的数据类型之间的转换拼接; 对于之前进行的文件上传操作,囊括单文件以及同名多文件和非同名多文件的编程方法,在生产中会遇到一个问题,如果上传的图片是同名的,那么在单文件上传的时候会将…

java 每种设计模式的作用,与应用场景

文章目录 前言java 每种设计模式的作用&#xff0c;与应用场景 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff0c;实在白嫖的话&#xff0…

Android - Context

一、概念 Context 是应用程序和系统之间的桥梁&#xff0c;用于获取全局消息、访问系统资源、调用应用程序级的操作。一般直接调用 Context 的方法或者调用接口时传入Context。 Android应用模型是基于组件的应用设计模式&#xff0c;组件的运行要有一个完整的Android工程环境。…

Linux基础指令笔记大全

Linux基础指令笔记大全 1. ls 指令2. pwd命令3. cd 指令4. touch指令5. mkdir指令6. rmdir指令 && rm 指令7. man指令8.cp指令9. mv指令10. cat 指令11. more指令12. less指令13. head指令14. tail指令15. 时间相关的指令1. **在显示方面&#xff0c;使用者可以设定欲显…

华为云云耀云服务器L实例评测 | 实例使用教学之综合导览

华为云云耀云服务器L实例评测 &#xff5c; 实例使用教学之综合导览 实例使用教学实例场景体验实例性能评测实例评测使用介绍华为云云耀云服务器 华为云云耀云服务器 &#xff08;目前已经全新升级为 华为云云耀云服务器L实例&#xff09; 华为云云耀云服务器是什么华为云云耀云…

上海亚商投顾:沪指探底回升 华为汽车概念股集体大涨

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 三大指数昨日探底回升&#xff0c;早盘一度集体跌超1%&#xff0c;随后震荡回暖&#xff0c;深成指、创业板指…

hive 知识总结

​编辑 社区公告教程下载分享问答JD 登 录 注册 01 hive 介绍与安装 1 hive介绍与原理分析 Hive是一个基于Hadoop的开源数据仓库工具&#xff0c;用于存储和处理海量结构化数据。它是Facebook 2008年8月开源的一个数据仓库框架&#xff0c;提供了类似于SQL语法的HQL&#xf…

第 5 章 数组和广义表(数组的顺序存储结构实现)

1. 背景说明 数组一旦被定义&#xff0c;它的维数和维界就不再改变。因此&#xff0c;除了结构的初始化和销毁之外&#xff0c;数组只有存取元素和修改元素值的操作。 2. 示例代码 1) status.h /* DataStructure 预定义常量和类型头文件 */ #include <string.h>#ifndef…

【论文精读】Chain-of-Thought Prompting Elicits Reasoning in Large Language Models

Chain-of-Thought Prompting Elicits Reasoning in Large Language Models 前言Abstract1 Introduction2 Chain-of-Thought Prompting3 Arithmetic Reasoning3,1 Experimental Setup3.2 Results3.3 Ablation Study3.4 Robustness of Chain of Thought 4 Commonsense Reasoning5…

通过Java Record提升代码质量:简洁而健壮的数据对象

为了提高开发效率和代码可读性&#xff0c;Java 14引入了一个新的特性 - Records&#xff08;记录类型&#xff09;。Records旨在简化和改进Java中的数据类定义&#xff0c;使得创建简单的数据传输对象&#xff08;DTO&#xff09;或值对象更加便捷。 什么是Java Record&#x…

Springboot接收http参数总结(最简单易懂)

1. 前端能携带请求参数的地方 http请求一半前端请求参数放在三个地方&#xff1a;请求头&#xff0c;请求查询参数&#xff08;Query String&#xff09;&#xff0c;请求体。 请求体需要获取HttpServletRequest对象才能获取。 2. 请求体常见格式 而请求体中可以存放多种格式…