当前位置: 首页 > news >正文

即时通信的方法和webSocket的具体使用

前言

之前遇到过需要即时通讯的场景,刚开始使用的是通过轮询的方式,定时器3秒向服务器请求一次数据,后面发现如果在手机端长时间打开使用此功能的页面,可能会发生手机发热,甚至卡顿的现象。最后改用webSocket,可以实现全双工通信,让服务器主动向客户端发送请求。

接下来先介绍一下即时通信的实现方法?

  1. 轮询(Polling):

    • 工作原理:客户端定时向服务器发送请求,询问是否有新数据可用。如果服务器有新数据,返回数据;如果没有,服务器返回空响应。客户端收到响应后立即再次发送请求,形成周期性的轮询过程。
    • 优点:实现简单,大部分浏览器和服务器都支持。
    • 缺点:频繁的请求和响应会导致不必要的网络开销,降低性能和效率。
    • 适用场景:适用于数据更新频率不高且实时性要求不高的场景。
  2. 长轮询(Long Polling):

    • 工作原理:客户端发送请求给服务器,服务器不立即返回响应,而是将请求挂起,等待有新数据时再返回响应。一旦客户端收到响应,立即再次发送请求,形成新的挂起请求。
    • 优点:相较于轮询,减少了不必要的网络请求,降低了网络开销。
    • 缺点:服务器需要维护大量挂起的请求,占用资源较多,不适用于高并发场景。
    • 适用场景:适用于数据更新不频繁,但要求实时性相对较高的场景。
  3. WebSocket:

    • 工作原理:WebSocket 是一种全双工通信协议,通过建立持久性的连接,客户端和服务器可以随时发送和接收消息。连接建立后,双方可以直接发送消息,不需要频繁的握手过程。
    • 优点:实现实时通信,降低了不必要的网络开销,性能高,支持跨域通信。
    • 缺点:需要服务器和客户端都支持 WebSocket 协议。
    • 适用场景:适用于需要实时通信的场景,如实时聊天、在线游戏等。
  4. Server-Sent Events(SSE):

    • 工作原理:SSE 是一种单向通信协议,允许服务器向客户端发送数据,但客户端不能向服务器发送数据。客户端通过 EventSource 对象订阅服务器的事件流,一旦有新数据可用,服务器会自动发送数据给客户端。
    • 优点:实现简单,不需要像 WebSocket 那样进行双向握手,适用于服务器向客户端推送数据。
    • 缺点:只支持单向通信,不适用于客户端向服务器发送请求。
    • 适用场景:适用于服务器主动向客户端推送实时数据的场景,如推送通知、实时监控等。

前端如何使用 WebSocket?

在前端中使用 WebSocket 非常简单,首先需要在浏览器中创建一个 WebSocket 对象,然后通过该对象与服务器建立连接。一旦连接建立成功,前端可以通过发送和接收消息来实现与服务器的实时通信。

1. 创建 WebSocket 对象

在 JavaScript 中,可以通过以下代码创建 WebSocket 对象:

const socket = new WebSocket('ws://example.com'); // 根据实际情况替换为服务器的 WebSocket 地址

在上述代码中,我们创建了一个 WebSocket 对象,传入服务器的 WebSocket 地址作为参数。WebSocket 地址的协议可以是 ws(未加密)或 wss(加密)。

2. 监听事件

一旦 WebSocket 连接建立成功,就可以通过监听事件来处理连接状态和消息的收发。

socket.onopen = () => {console.log('WebSocket连接已建立');
};socket.onmessage = event => {const message = event.data;console.log('收到消息:', message);
};socket.onclose = () => {console.log('WebSocket连接已关闭');
};socket.onerror = error => {console.error('WebSocket连接错误:', error);
};

在上述代码中,我们监听了 onopen 事件(连接建立)、onmessage 事件(收到消息)、onclose 事件(连接关闭)、onerror 事件(连接错误)。每当相应的事件触发时,我们通过回调函数来处理相应的逻辑。

3. 发送和接收消息

一旦 WebSocket 连接建立成功,就可以通过 send() 方法来发送消息,同时通过 onmessage 事件来接收消息。

// 发送消息
socket.send('Hello, WebSocket!');// 接收消息在上面的监听代码中已经处理

以上代码演示了如何在前端中创建 WebSocket 连接、发送和接收消息。当服务器和客户端建立连接后,它们可以随时通过 send() 方法和 onmessage 事件来实现实时通信。

4.websocket的心跳机制

WebSocket中心跳机制的作用主要有以下几个方面:

  1. 保持连接活跃
    WebSocket是一种双向通信协议,一旦建立连接,服务器和客户端之间可以实时传输数据。但由于网络等原因,长时间没有数据传输可能导致连接的关闭。心跳机制通过定期发送心跳包,即使没有实际数据交互,也能保持连接的活跃状态,防止连接被中断。

  2. 确认服务器存活状态
    通过心跳机制,客户端可以定期向服务器发送心跳包,并等待服务器的响应。如果一段时间内没有收到服务器的响应,客户端可以判断服务器可能出现了故障或断开连接,并根据情况进行相应的处理,如重新连接服务器。

  3. 优化网络资源利用
    心跳机制可以定时发送较小的数据包,相较于大量数据传输,心跳包的资源占用较小。这有助于减少网络资源的浪费,并提高数据传输效率。

  4. 错误处理与重连
    通过心跳机制,客户端可以及时检测到连接断开的情况,并进行错误处理和重连操作。在网络环境不稳定或服务器故障的情况下,心跳机制可以帮助客户端更快地恢复与服务器的连接。

  5. 连接状态监控
    心跳机制可以用于监控WebSocket连接的状态,包括连接建立、断开、异常等状态。这有助于客户端了解连接状态,做出相应的操作。

总体而言,WebSocket中心跳机制的作用是维持连接的稳定性和可靠性,确保连接保持活跃,并及时处理异常情况,提高通信效率和用户体验。
使用:

const webSocketUrl = 'ws://example.com'; // WebSocket服务器地址
const heartBeatInterval = 5000; // 心跳间隔时间,单位为毫秒let webSocket = null;
let heartBeatTimer = null;function initWebSocket() {webSocket = new WebSocket(webSocketUrl);webSocket.onopen = () => {console.log('WebSocket连接已建立');// 建立连接后开始发送心跳包startHeartBeat();};webSocket.onmessage = (event) => {// 处理服务器发送的消息console.log('收到服务器消息:', event.data);};webSocket.onclose = () => {console.log('WebSocket连接已关闭');// 连接关闭后停止心跳包stopHeartBeat();// 可根据需要重新连接// reconnect();};
}function startHeartBeat() {// 每隔一段时间发送心跳包heartBeatTimer = setInterval(() => {if (webSocket.readyState === WebSocket.OPEN) {webSocket.send('ping'); // 发送心跳包}}, heartBeatInterval);
}function stopHeartBeat() {// 停止心跳包发送clearInterval(heartBeatTimer);
}// 初始化WebSocket连接
initWebSocket();

案例

实现一个简易的聊天功能
1.创建一个文件夹
2.初始化

npm init -y
npm install websocket

3.创建websocket服务端,命名为server.js

const websocket=require("websocket").server
const http=require('http');
const httpServer = http.createServer().listen(8080, ()=>{console.log('cyl: ','http://localhost:8080');
})
const websocketServer = new websocket({httpServer: httpServer,autoAcceptConnections: false
})
const conArr = []
websocketServer.on('request', function(request) {// 这就是一次客户端发送的消息// websocket 需要将这个链接保存起来// 只要客户端和服务器没有断开,这个链接必须在// 客户端与服务端的通信都是从这个链接上通信const connection = request.accept()// 每次接收一个链接,将它存放在数组里面conArr.push(connection)console.log(connection)// 监听客户端发送的消息connection.on('message', function(message) {console.log(message);// 发送消息给客户端(广播到各个客户端)// 后面加上 utf8Data 编码// 要将所有的链接全部发出去,才可以让每个客户端接收到其他传来的数据for(let i = 0; i < conArr.length; i++) {conArr[i].send(message.utf8Data)}})
})

4.创建传送给客户端的文件index.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><!-- 需要一进入浏览器就要建立链接 --><!-- 点击按钮发送消息给服务器 -->输入姓名:<input type="text" id="uName"><br>输入消息:<input type="text" id="context"><button id="btn"> 点击发送消息 </button><div id="charRoom"></div><script>// 用户名const uName = document.getElementById('uName')// 文本框内容const context = document.getElementById('context')// 点击按钮const btn = document.getElementById('btn')// 要显示聊天室的区域const charRoom = document.getElementById('charRoom')// 实例化 websocket// 必须加 'ws://localhost:8080' ws 协议,后面是开启的服务端接口const websocket = new WebSocket('ws://localhost:8080')// 打开事件websocket.onopen = function() {// 获取当前链接的状态// 1 是建立了链接console.log(websocket.readyState);}// 点击发送消息的事件btn.onclick = function() {// 将用户名和要发送的内容放在一个对象中,一起传送给后端const values = {uName: uName.value,context: context.value}// 清空文本框的内容uName.value = ''context.value = ''// 通过 websocket发送消息websocket.send(JSON.stringify(values))}// 接收服务器返回的消息websocket.onmessage = function(data) {console.log("服务器返回的数据",data)// 服务器返回过来的聊天信息const chatS = JSON.parse(data.data)// 添加到页面上charRoom.innerHTML += `<strong>${chatS.uName}:</strong><span>${chatS.context}</span><br />`}// 服务器断开连接,客户端会触发websocket.onclose = function() {}</script>
</body>
</html>

4.启动服务端

node server.js

服务启动成功
在这里插入图片描述
在这里插入图片描述

相关文章:

即时通信的方法和webSocket的具体使用

前言 之前遇到过需要即时通讯的场景&#xff0c;刚开始使用的是通过轮询的方式&#xff0c;定时器3秒向服务器请求一次数据&#xff0c;后面发现如果在手机端长时间打开使用此功能的页面&#xff0c;可能会发生手机发热&#xff0c;甚至卡顿的现象。最后改用webSocket&#xf…...

HTML 速查列表

HTML 速查列表 HTML 速查列表. 你可以打印它&#xff0c;以备日常使用。 HTML 基本文档 <!DOCTYPE html> <html> <head> <title>文档标题</title> </head> <body> 可见文本... </body> </html> 基本标签&#xff08;Ba…...

Hadoop集成Hive

一、环境与软件准备 说明&#xff1a;服务器已用主机名代替&#xff0c;可根据自己的需求&#xff0c;改为IP地址 环境 服务器组件masterNameNode、DataNode、Nodemanager、ResourceManager、Hive、Hive的metastore、Hive的hiveserver2、mysqlSecondarySecondaryNameNode、D…...

MyBatis查询数据库

目录 一、什么是MyBatis 二、搭建MyBatis开发环境 &#x1f345;添加MyBatis依赖 &#x1f345;在数据库添加数据 &#x1f345;设置MyBatis配置 &#x1f388;数据库的相关连接信息&#x1f388;xml的保存和设置路径 三、使用MyBatis模式和语法操作数据库 &#x1f34…...

RVM问题记录 - Error running ‘__rvm_make -j10‘

文章目录 前言开发环境问题描述问题分析解决方案最后 前言 公司新到一台电脑需要配置开发环境&#xff0c;在用RVM安装Ruby时遇到了一个奇怪的问题。 开发环境 RVM: 1.29.12OpenSSL: 3.1.1 问题描述 执行命令安装Ruby 3.0版本&#xff1a; rvm install ruby-3.0.0在编译阶…...

VIS for AI :ConvNetJS

1.简单介绍&#xff1a; ConvNetJS是由斯坦福大学计算机科学系的Andrej Karpathy开发的一个深度学习框架&#xff0c;用于在浏览器中运行卷积神经网络&#xff08;ConvNet&#xff09;。ConvNetJS可以帮助开发人员在客户端&#xff08;浏览器&#xff09;上进行深度学习任务&a…...

【Python入门系列】第二十篇:Python区块链和加密货币

文章目录 前言一、区块链基础知识1.1 什么是区块链1.2 区块链的工作原理 1.3 区块链的优势和应用场景二、Python实现区块链2.1 创建区块类2.2 创建区块链类2.3 添加区块和验证区块链 三、加密货币基础知识3.1 什么是加密货币3.2 加密货币的工作原理3.3 加密货币的挖矿和交易 四…...

MySQL 服务器的调优策略

点击上方↑“追梦 Java”关注&#xff0c;一起追梦&#xff01; 在工作中&#xff0c;我们发现慢查询一般有2个途径&#xff0c;一个是被动的&#xff0c;一个是主动的。被动的是当业务人员反馈某个查询界面响应的时间特别长&#xff0c;你才去处理。主动的是通过通过分析慢查询…...

Educational Codeforces Round 152 (Rated for Div. 2)

B这个题目在20分钟的时候发现了取模的规律&#xff0c;但是在写法上我竟然犹豫了&#xff0c;这影响了我后面题目的心态 过于可惜了 但是没关系&#xff0c;现在不会&#xff0c;之后就会写了 这里强调一下&#xff0c;sort不会改变原先的顺序&#xff0c;就是说如果两个相等的…...

CSPM难度大吗?对比pmp怎么样?

CSPM证书是刚出来的&#xff0c;难度不会很大&#xff0c;大家都知道 PMP 证书是从国外引进的&#xff0c;近几年很热门&#xff0c;持证人数已经高达 90 余万了&#xff0c;但是目前我们和老美关系大家有目共睹&#xff0c;一直推国际标准和美国标准感觉有点奇怪。 现在新出台…...

Android.mk中的LOCAL_OVERRIDES_PACKAGES用法

Android.mk中的LOCAL_OVERRIDES_PACKAGES用法_mk local_over_觅风者的博客-CSDN博客 Android.mk中的LOCAL_OVERRIDES_PACKAGES的用法说明可以参考以下文章&#xff1a; Android.mk覆盖替换LOCAL_OVERRIDES_PACKAGES 此变量可以使其他的模块不加入编译 项目中遇到的问题&…...

Matlab遍历文件及直方图统计

参考链接&#xff1a; 使用MATLAB遍历文件 strtrim用法 strsplit用法 cell单元数据使用{} close all; dir_path C:/Users/; fileFolder ls(dir_path); fileNum length(fileFolder(:,1)) - 2; for i 3:(3fileNum-1)file_path strcat(dir_path, strtrim(fileFolder(i,:)))…...

为什么要格式化硬盘?硬盘格式化了数据怎么恢复

在计算机维护和数据管理中&#xff0c;格式化硬盘是一个常见的操作。本文将探讨为什么需要对硬盘进行格式化以及当数据丢失时如何恢复。 ▌格式化硬盘是什么意思&#xff1a; 硬盘格式化是对磁盘或其分区进行初始化的一种操作&#xff0c;它会清除磁盘或分区中的所有文件。因此…...

PHP注册、登陆、6套主页-带Thinkphp目录解析-【白嫖项目】

强撸项目系列总目录在000集 PHP要怎么学–【思维导图知识范围】 文章目录 本系列校训本项目使用技术 上效果图主页注册&#xff0c;登陆 phpStudy 设置导数据库项目目录如图&#xff1a;代码部分&#xff1a;控制器前台的首页 其它配套页面展示直接给第二套方案的页面吧第三套…...

antDesignMobile中Switch配合Form使用无效解决方案

介绍 Form和Switch合起来使用无效的原因就是因为Form.Item给Switch的是value值&#xff0c;而Switch中监听的是checked&#xff1b;所以说我们只需要做一层二次封装即可。非常简单~如下本文以antd-mobile举例&#xff0c;其他antd框架解决方案一致&#xff01;&#xff01;&am…...

记录springboot在k8s下无法读取文件问题

//加载配置文件 File file ResourceUtils.getFile("classpath:/template/job.yaml"); /对象映射 V1Job v1Job (V1Job) Yaml.load(file); 开发的时候使用上面的方法可以读取文件数据&#xff0c;但是部署到k8s容器中之后&#xff0c;读取文件出现报错&#xff0c…...

数据湖如何为企业带来9%的高增长?可否取代数据仓库?

什么是数据湖&#xff1f; 数据湖是一个集中的存储库&#xff0c;允许您以任何规模存储所有结构化和非结构化数据。您可以按原样存储数据&#xff0c;而不必首先构造数据&#xff0c;并运行不同类型的分析—从仪表板和可视化到大数据处理、实时分析和机器学习&#xff0c;以指…...

P2669 [NOIP2015 普及组] 金币

题目背景 NOIP2015 普及组 T1 题目描述 国王将金币作为工资&#xff0c;发放给忠诚的骑士。第一天&#xff0c;骑士收到一枚金币&#xff1b;之后两天&#xff08;第二天和第三天&#xff09;&#xff0c;每天收到两枚金币&#xff1b;之后三天&#xff08;第四、五、六天&a…...

【2023】华为OD机试真题Java CC++ Python JS Go-题目0250-选修课

题目0250-选修课 题目描述 现有两门选修课,每门选修课都有一部分学生选修,每个学生都有选修课的成绩,需要你找出同时选修了两门选修课的学生,先按照班级进行划分,班级编号小的先输出,每个班级按照两门选修课成绩和的降序排序,成绩相同时按照学生的学号升序排序。 输入…...

lama cleaner

这里写自定义目录标题 安装参数包含的额外plugins 代码结构FreehandBackground RemovalInteractiveSeg 安装 conda create --name lamacleaner python3.10 pip install -r requirements.txt pip install gfpgan pip install realesrgan pip install rembg pip install .如果…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库&#xff0c;提供了高效、安全的文本格式化功能&#xff0c;是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…...

comfyui 工作流中 图生视频 如何增加视频的长度到5秒

comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗&#xff1f; 在ComfyUI中实现图生视频并延长到5秒&#xff0c;需要结合多个扩展和技巧。以下是完整解决方案&#xff1a; 核心工作流配置&#xff08;24fps下5秒120帧&#xff09; #mermaid-svg-yP…...

Mac flutter环境搭建

一、下载flutter sdk 制作 Android 应用 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 1、查看mac电脑处理器选择sdk 2、解压 unzip ~/Downloads/flutter_macos_arm64_3.32.2-stable.zip \ -d ~/development/ 3、添加环境变量 命令行打开配置环境变量文件 ope…...