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

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

关于easyexcel动态下拉选问题处理

前些日子突然碰到一个问题&#xff0c;说是客户的导入文件模版想支持部分导入内容的下拉选&#xff0c;于是我就找了easyexcel官网寻找解决方案&#xff0c;并没有找到合适的方案&#xff0c;没办法只能自己动手并分享出来&#xff0c;针对Java生成Excel下拉菜单时因选项过多导…...

十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建

【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...

二维FDTD算法仿真

二维FDTD算法仿真&#xff0c;并带完全匹配层&#xff0c;输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...

SpringCloud优势

目录 完善的微服务支持 高可用性和容错性 灵活的配置管理 强大的服务网关 分布式追踪能力 丰富的社区生态 易于与其他技术栈集成 完善的微服务支持 Spring Cloud 提供了一整套工具和组件来支持微服务架构的开发,包括服务注册与发现、负载均衡、断路器、配置管理等功能…...

本地部署drawDB结合内网穿透技术实现数据库远程管控方案

文章目录 前言1. Windows本地部署DrawDB2. 安装Cpolar内网穿透3. 实现公网访问DrawDB4. 固定DrawDB公网地址 前言 在数字化浪潮席卷全球的背景下&#xff0c;数据治理能力正日益成为构建现代企业核心竞争力的关键因素。无论是全球500强企业的数据中枢系统&#xff0c;还是初创…...

【从零学习JVM|第二篇】字节码文件

前言&#xff1a; 通过了解字节码文件可以帮助我们更容易的理解JVM的工作原理&#xff0c;所以接下来&#xff0c;我们来介绍一下字节码文件。 目录 前言&#xff1a; 正确的打开字节码文件 字节码文件组成 1. 魔数&#xff08;Magic Number&#xff09; 2. 版本号&…...