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

news2024/11/29 1:43:47

前言

之前遇到过需要即时通讯的场景,刚开始使用的是通过轮询的方式,定时器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 事件来实现实时通信。

案例

实现一个简易的聊天功能
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

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

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

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

相关文章

js 过滤两个数组中的相同元素

1. filter 和 find 、some ,includes结合使用 let arr [1, 2, 3, 4, 5]; let arr2 [3, 4, 5, 6, 7];const arr3 arr.filter((item) > arr2.includes(item)); const arr4 arr.filter((item) > arr2.find((item2) > item2 item)); const arr5 arr.filter((item)…

Vue3+ElementPlus+TS实现右上角消息数量实时更新

Vue3ElementPlusTS实现右上角消息数量实时更新 背景 项目需求&#xff0c;前端右上角铃铛图标 显示接收到的消息通知&#xff0c;并且显示消息数量以及实时更新。&#xff08;一般是点击操作按钮后增加一条消息通知&#xff0c;图标上的数字也随之更新&#xff09; 【原来的想…

uniapp 微信小程序 姓名脱敏 substring报错问题:Cannot read property ‘substring‘ of undefined

效果图&#xff1a; 刘德华----------刘* 加v-if判断是因为如果是后台数据返回的字段&#xff0c;如果不加判断&#xff0c;substring的时候有可能数据还没渲染完&#xff0c;会报错 <text v-if"userName">{{userName.substring(0, 1) *}}</text>

【Duilib】错误:红色波浪线,无法打开源文件“stdafx.h”

问题 Duilib工程可以编译&#xff0c;但是智能提示&#xff1a;错误&#xff1a;红色波浪线&#xff0c;无法打开源文件“stdafx.h”。 解决方法 1、确认stdafx.h文件位置在vcxproj文件同一目录&#xff0c;并且stdafx.h已添加至DUILIB工程。 2、DUILIB项目属性\C/C\常规 页面…

(css)原生html实现遮罩层弹窗

(css)原生html实现遮罩层弹窗 效果&#xff1a; html <div class"overlay"><div class"content"><!-- 需要遮罩的内容 --> <el-table :data"tableData" size"mini" class"table-class" border stripe…

AutoSAR系列讲解(实践篇)7.4-实验:配置SWCRTE

注意: 实验篇是重点,有条件的同学最好跟着做一遍,然后回头对照着7.1-7.3理解其配置的目的和意义。实验下篇将在7.7节中继续做 一、实验概览 1、实验目的 通过本次实验,主要是让大家对Dev的配置有一个全流程的学习。这里会用到前两节的内容,将其串联起来,让大家能完整的…

【git基本使用】

初识git 一、git安装 1.1 Linux-centos 如果你的的平台是centos&#xff0c;安装git相当简单&#xff0c;以我的centos7.6为例&#xff1a; ⾸先&#xff0c;你可以试着输⼊Git&#xff0c;看看系统有没有安装Git&#xff1a; git-bash: git: command not found 出现像上⾯…

linux同时安装JDK8和JDK11并指定默认版本

1、安装OpenJDK11 yum install java-11-openjdk2、安装OpenJDK 8 yum install java-8-openjdk3.查看Java版本列表 alternatives --list4、查看当前Java版本 java -version5、更改Java版本 alternatives --config java6、设置JAVA_HOME环境变量 vi /etc/profile.d/java.sh…

多线程(JavaEE初阶系列3)

目录 前言&#xff1a; 1.中断一个线程 2.等待一个线程-join() 2.1join()无参调用的使用 2.2join()有参调用的使用 3.线程的状态 3.1观察线程的所有状态 4.多线程带来的风险—线程安全 4.1观察线程不安全 4.2该问题出现的原因 4.3线程不安全问题的解决 4.3.1synchro…

【PostgreSQL内核学习(九)—— 查询执行(数据定义语句执行)】

数据定义语句执行 概述数据定义语句执行流程执行示例 声明&#xff1a;本文的部分内容参考了他人的文章。在编写过程中&#xff0c;我们尊重他人的知识产权和学术成果&#xff0c;力求遵循合理使用原则&#xff0c;并在适用的情况下注明引用来源。 本文主要参考了《PostgresSQL…

【Python数据分析】Python基础知识篇

&#x1f389;欢迎来到Python专栏~Python基础知识篇 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;Python学习专栏 文章作者技术和水平有限&#xff0c;如果文中出现错误&#xff0c;希望大…

vue中使用原生的table合并行

完整的代码&#xff1a; <template><table border"1"><thead><tr><th>Name</th><th>Value</th></tr></thead><tbody><template v-for"(item, index) in tableData"><templat…

Hbase基本原理剖析

一、基本原理 数据存储使用HBase来承接&#xff0c;HBase是一个开源的、面向列&#xff08;Column-Oriented&#xff09;、适合存储海量非结构化数据或半结构化数据的、具备高可靠性、高性能、可灵活扩展伸缩的、支持实时数据读写的分布式存储系统。更多关于HBase的信息&#…

fpga4fun—发光二极管

发光二极管电子基础知识 LED&#xff08;发光二极管&#xff09;是一种半导体器件&#xff0c;当电流通过它时会产生光。 LED 符号看起来像一个二极管&#xff0c;带有阳极 &#xff08;&#xff09; 和阴极 &#xff08;-&#xff09;。 LED 的作用类似于二极管 - 单向导电&…

电脑新装系统优化,win10优化,win10美化

公司发了新的笔记本&#xff0c;分为几步做 1.系统优化,碍眼的关掉。防火墙关掉、页面美化 2.安装必备软件及驱动 3.数据迁移 4.开发环境配置 目录 目录复制 这里写目录标题 目录1.系统优化关掉底部菜单栏花里胡哨 2.安装必备软件及驱动新电脑安装360 1.系统优化 关掉底部菜单…

linux驱动开发入门(学习记录)

2023.7.6及7.7 概述了解 一 1.驱动框架 2. 字符设备 块设备&#xff0c;存储相关 网络设备驱动 不一定属于某一种类型二 1.获取外设或传感器数据&#xff0c;控制外设&#xff0c;数据会提交给应用程序 2.编写一个驱动&#xff0c;及测试应用程序 app。驱动和应用完全分开 3.驱…

程序员进阶之路:程序环境和预处理

目录 前言 程序的翻译环境和执行环境 翻译环境 运行环境 预处理&#xff08;预编译&#xff09; 预定义符号 #define #define 定义标识符 #define 定义宏 #define 替换规则 #和## #的作用 ##的作用 带副作用的宏参数 宏和函数对比 命名约定 #undef 命令行定义 条件…

通过v-for生成的input无法连续输入

部分代码&#xff1a;通过v-for循环生成el-form-item&#xff0c;生成多个描述输入框 更改之前的代码&#xff08;key绑定的是item&#xff09;&#xff1a; <el-form-item class"forminput" v-for"(item,index) in formdata.description" :key"…

【Linux -- 优先级 -- nice,renice 】

Linux – 优先级 – nice,renice 文章目录 Linux -- 优先级 -- nice,renice一、优先级1.Priority(PRI)2.nice(NI) 二、nice命令三、renice命令总结 一、优先级 CPU调度是指每个进程被CPU运行的规则,如果休眠的进程同时被唤醒,那CPU应该先处理哪个进程呢? 1.Priority(PRI) L…

Langchain 和 Chroma 的集成

Langchain 和 Chroma 的集成 1. Chroma2. 基本示例​3. 基本示例(包括保存到磁盘)4. 将 Chroma Client 传递到 Langchain ​5. 基本示例(使用 Docker 容器)6. 更新和删除7. 带分数的相似性搜索​ 1. Chroma Chroma 是一个人工智能原生开源矢量数据库&#xff0c;专注于开发人员…