当前位置: 首页 > 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 .如果…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...

C++ 设计模式 《小明的奶茶加料风波》

&#x1f468;‍&#x1f393; 模式名称&#xff1a;装饰器模式&#xff08;Decorator Pattern&#xff09; &#x1f466; 小明最近上线了校园奶茶配送功能&#xff0c;业务火爆&#xff0c;大家都在加料&#xff1a; 有的同学要加波霸 &#x1f7e4;&#xff0c;有的要加椰果…...

c# 局部函数 定义、功能与示例

C# 局部函数&#xff1a;定义、功能与示例 1. 定义与功能 局部函数&#xff08;Local Function&#xff09;是嵌套在另一个方法内部的私有方法&#xff0c;仅在包含它的方法内可见。 • 作用&#xff1a;封装仅用于当前方法的逻辑&#xff0c;避免污染类作用域&#xff0c;提升…...