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

在nodejs中实现实时通信的几种方式

在nodejs中实现实时通信的几种方式

在当今世界中,实时通信至关重要。无论是聊天应用程序还是实时体育更新,实时通信都是保持用户活跃度所必需的。Node.js 因其速度、可扩展性和可靠性而成为开发实时应用程序的流行工具。在本文中,我们将探讨为什么 Node.js 是实时通信的理想选择以及如何实现它。

为什么使用 Node.js 进行实时通信?

Node.js 构建在 GoogleV8 JavaScript 引擎之上,该引擎以其高性能而闻名。这使得 Node.js 成为构建需要速度和可扩展性的实时通信应用程序的完美工具。Node.js 也是事件驱动的,这意味着它可以同时处理多个连接,非常适合构建实时应用程序。

协议和库的类型

Node.js 提供了多种方式来实现实时数据通信。Node.js 中实时数据通信的一些流行库是:

socket.io

socket.io是一个流行的实时通信库。它使用 WebSockets 作为传输层来提供客户端和服务器之间的实时通信。socket.io 提供了许多功能,例如自动重新连接、对二进制数据的支持以及不支持 WebSocket 的环境的回退选项。

在这里插入图片描述

示例代码

服务器端代码:

const express = require('express');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);io.on('connection', (socket) => {console.log('User connected');socket.on('chat:message', (data) => {io.emit('chat:message', data);});socket.on('disconnect', () => {console.log('User disconnected');});
});const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {console.log(`Server listening on port ${PORT}`);
});

客户端代码:

<!DOCTYPE html>
<html>
<head><title>Socket.IO Chat</title>
</head>
<body><div id="messages"></div><form id="chat-form"><input type="text" id="message-input"><button type="submit">Send</button></form><script src="/socket.io/socket.io.js"></script><script>const socket = io();const messagesDiv = document.getElementById('messages');const chatForm = document.getElementById('chat-form');const messageInput = document.getElementById('message-input');chatForm.addEventListener('submit', (event) => {event.preventDefault();const message = messageInput.value.trim();if (message) {socket.emit('chat:message', message);messageInput.value = '';}});socket.on('chat:message', (data) => {const messageDiv = document.createElement('div');messageDiv.innerText = data;messagesDiv.appendChild(messageDiv);});</script>
</body>
</html>

WebSockets

WebSockets 是一种支持客户端和服务器之间实时通信的协议。它通过单个 TCP 连接提供全双工通信通道,允许客户端和服务器之间进行实时数据交换。ws模块可用于实现 WebSockets

在这里插入图片描述

示例代码

服务器端代码:

const WebSocket = require('ws');
const server = new WebSocket.Server({ port: 3000 });server.on('connection', (socket) => {console.log('User connected');socket.on('message', (message) => {server.clients.forEach((client) => {if (client.readyState === WebSocket.OPEN) {client.send(message);}});});socket.on('close', () => {console.log('User disconnected');});
});

客户端代码:

<!DOCTYPE html>
<html>
<head><title>WebSockets Chat</title>
</head>
<body><div id="messages"></div><form id="chat-form"><input type="text" id="message-input"><button type="submit">Send</button></form>
<script>const socket = new WebSocket('ws://localhost:3000');const messagesDiv = document.getElementById('messages');const chatForm = document.getElementById('chat-form');const messageInput = document.getElementById('message-input');chatForm.addEventListener('submit', (event) => {event.preventDefault();const message = messageInput.value.trim();if (message) {socket.send(message);messageInput.value = '';}});socket.addEventListener('message', (event) => {const messageDiv = document.createElement('div');messageDiv.innerText = event.data;messagesDiv.appendChild(messageDiv);});</script>
</body>
</html>

服务器发送事件

服务器发送事件是一个简单的协议,允许服务器通过 HTTP 连接向客户端发送事件。它非常适合需要单向通信的应用程序,例如现场体育赛事比分或股票市场更新。该模块称为sse,可用于实现服务器发送事件。

在这里插入图片描述

示例代码

服务器端代码:

const express = require('express');
const app = express();app.get('/events', (req, res) => {res.writeHead(200, {'Content-Type': 'text/event-stream','Cache-Control': 'no-cache','Connection': 'keep-alive'});const interval = setInterval(() => {res.write(`data: ${new Date().toLocaleTimeString()}\n\n`);}, 1000);req.on('close', () => {clearInterval(interval);res.end();});
});const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {console.log(`Server listening on port ${PORT}`);
});

客户端代码:

<!DOCTYPE html>
<html>
<head><title>Server-Sent Events Clock</title>
</head>
<body><div id="clock"></div>
<script>const source = new EventSource('/events');const clockDiv = document.getElementById('clock');source.addEventListener('message', (event) => {clockDiv.innerText = event.data;});</script>
</body>
</html>

WebRTC

WebRTC 是一种实时通信协议,允许浏览器建立点对点连接。它在客户端之间提供低延迟的通信通道,而无需服务器。wrtc库可用于实现 WebRTC

在这里插入图片描述

示例代码

服务器端代码:

const express = require('express');
const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http);
const { RTCPeerConnection, RTCSessionDescription, RTCIceCandidate } = require('wrtc');
app.use(express.static('public'));io.on('connection', socket => {console.log('Client connected:', socket.id);let pc = new RTCPeerConnection();socket.on('offer', offer => {console.log('Received offer');pc.setRemoteDescription(new RTCSessionDescription(offer)).then(() => {return navigator.mediaDevices.getUserMedia({ audio: true, video: true });}).then(stream => {console.log('Got local stream');stream.getTracks().forEach(track => {pc.addTrack(track, stream);});pc.onicecandidate = event => {if (event.candidate) {socket.emit('candidate', event.candidate);}};pc.ontrack = event => {console.log('Received remote stream');socket.emit('answer', pc.localDescription);};pc.createAnswer().then(answer => {return pc.setLocalDescription(answer);}).catch(error => {console.log('Error creating answer:', error);});}).catch(error => {console.log('Error getting user media:', error);});});socket.on('disconnect', () => {console.log('Client disconnected:', socket.id);pc.close();});
});const PORT = process.env.PORT || 3000;
http.listen(PORT, () => {console.log(`Server listening on port ${PORT}`);
});

客户端代码:

<html><head><meta charset="UTF-8"><title>WebRTC Example</title></head><body><h1>WebRTC Example</h1><div><video id="localVideo" autoplay></video><video id="remoteVideo" autoplay></video></div><div><button id="callButton">Call</button><button id="hangupButton" disabled>Hang Up</button></div><script src="/socket.io/socket.io.js"></script><script>const socket = io.connect('http://localhost:3000');const localVideo = document.getElementById('localVideo');const remoteVideo = document.getElementById('remoteVideo');const callButton = document.getElementById('callButton');const hangupButton = document.getElementById('hangupButton');let pc = new RTCPeerConnection();hangupButton.disabled = true;callButton.onclick = () => {console.log('Calling');navigator.mediaDevices.getUserMedia({ audio: true, video: true }).then(stream => {console.log('Got local stream');localVideo.srcObject = stream;stream.getTracks().forEach(track => {pc.addTrack(track, stream);});pc.onicecandidate = event => {if (event.candidate) {socket.emit('candidate', event.candidate);}};pc.ontrack = event => {console.log('Received remote stream');remoteVideo.srcObject = event.streams[0];};pc.createOffer().then(offer => {return pc.setLocalDescription(offer);}).then(() => {socket.emit('offer', pc.localDescription);}).catch(error => {console.log('Error creating offer:', error);});hangupButton.disabled = false;hangupButton.onclick = () => {console.log('Hanging up');pc.close();remoteVideo.srcObject = null;hangupButton.disabled = true;callButton.disabled = false;};}).catch(error => {console.log('Error getting user media:', error);});};socket.on('answer', answer => {console.log('Received answer');pc.setRemoteDescription(new RTCSessionDescription(answer)).catch(error => {console.log('Error setting remote description:', error);});});socket.on('candidate', candidate => {console.log('Received candidate');pc.addIceCandidate(new RTCIceCandidate(candidate)).catch(error => {console.log('Error adding ice candidate:', error);});});</script></body>
</html>

MQTT

mqtt 是一种轻量级消息传递协议,非常适合 IoT 应用程序。它为客户端和服务器之间的通信提供了发布/订阅模型。该模块称为mqtt,可用于实现 mqtt

在这里插入图片描述

示例代码

发布者端代码:

const mqtt = require('mqtt');
const client = mqtt.connect('mqtt://test.mosquitto.org');client.on('connect', () => {console.log('connected to MQTT broker');setInterval(() => {client.publish('test', 'Hello MQTT');}, 1000);
});client.on('error', (error) => {console.log(error);
});

订阅者端代码:

const mqtt = require('mqtt');
const client = mqtt.connect('mqtt://test.mosquitto.org');client.on('connect', () => {console.log('connected to MQTT broker');client.subscribe('test', (error) => {if (error) {console.log(error);}});
});client.on('message', (topic, message) => {console.log(`${topic}: ${message}`);
});client.on('error', (error) => {console.log(error);
});

如何确保这种通信的安全

安全性对于任何实时通信应用程序都是至关重要的。可以使用crypto模块,用于保护客户端和服务器之间的通信。该模块提供加密和解密功能,使得在客户端和服务器之间发送加密消息成为可能。

此外,每种类型都有模块,例如,在 WebSocket 中,有ws模块,安全的方法是用https而不是http包装它。

结论

Node.js 因其速度、可扩展性和可靠性而成为构建实时通信应用程序的绝佳选择。其事件驱动架构使得同时处理多个连接成为可能,并且V8 JavaScript引擎的使用确保了高性能能力。在 socket.io 等库的帮助下,使用 Node.js 构建实时通信应用程序非常简单。

然而,在处理实时通信应用程序时,安全性至关重要,并且必须使用加密来保护客户端和服务器之间的通信。

还提供了实现实时数据通信的各种方法,每种方法都有自己的一组功能和优点。选择正确的方法取决于您的应用程序的具体要求。socket.ioWebSockets 是最流行的实时通信方法,而服务器发送事件、WebRTCMQTT 适用于特定用例。

总体而言,Node.js 是构建实时通信应用程序的强大工具,对于任何需要实时通信的项目都值得考虑。

相关文章:

在nodejs中实现实时通信的几种方式

在nodejs中实现实时通信的几种方式 在当今世界中&#xff0c;实时通信至关重要。无论是聊天应用程序还是实时体育更新&#xff0c;实时通信都是保持用户活跃度所必需的。Node.js 因其速度、可扩展性和可靠性而成为开发实时应用程序的流行工具。在本文中&#xff0c;我们将探讨…...

【tg】 7 GroupInstanceCustomImpl

group GroupInstanceCustomImpl 核心GroupInstanceCustomInternal G:\CDN\P2P-DEV\tdesktop-offical\Telegram\ThirdParty\tgcalls\tgcalls\group\GroupInstanceCustomImpl.h 最核心是是GroupInstanceCustomInternal: private:std::shared_ptr<Threads> _threads;std::u…...

kubernates 集群实战-安装K3s集群

安装K3s集群 安装K3s集群环境准备安装 docker主节点安装work 节点验证环境 安装K3s集群 K3S是一种轻量级的Kubernetes发行版&#xff0c;安装和运行只需要一个二进制文件。相比之下&#xff0c;K8S需要更多的步骤和资源来安装和部署&#xff0c;例如设置etcd集群、安装控制平面…...

通俗介绍:什么是 Redis ?

刚接触 Redis 的伙伴们可能会因为不熟悉而感到困惑。本文简述 Redis 是什么、有哪些作用的问题&#xff0c;是一篇短浅而入门级别的文章。 Redis官网&#xff1a;Redis 打开 Redis 官网可以看到&#xff0c;官方对 Redis 的介绍是这样的&#xff1a;The open source, in-memo…...

蓝桥算法赛(摆玩具)

问题描述 小蓝是一个热爱收集玩具的小伙子&#xff0c;他拥有 n 个不同的玩具。 这天&#xff0c;他把 n 个玩具按照高度顺序从矮到高摆放在了窗台上&#xff0c;然后&#xff0c;他希望将这些玩具分成 k 个段&#xff0c;使得所有分段的极差之和尽可能小。 具体来说&…...

vueDay04——v-if else show

一、v-if的使用 我们可以像c语言一样去使用v-if结构 比如单用v-if&#xff0c;连用v-if v-else&#xff0c;或者是v-if v-else-if v-else 注意&#xff1a; 1.v-if v-else-if需要绑定值,而v-else不需要绑定值 2.if结构可以用在不同的标签类型之间 <div v-if"fir…...

大数据技术学习笔记(二)—— Hadoop 运行环境的搭建

目录 1 准备模版虚拟机hadoop1001.1 修改主机名1.2 修改hosts文件1.3 修改IP地址1.3.1 查看网络IP和网关1.3.2 修改IP地址 1.4 关闭防火墙1.5 创建普通用户1.6 创建所需目录1.7 卸载虚拟机自带的open JDK1.8 重启虚拟机 2 克隆虚拟机3 在hadoop101上安装JDK3.1 传输安装包并解压…...

leetcode系列(双语)002——GO两数相加

文章目录 两数相加 | Add Two Numbers示例个人解答官方解答扩展Algorithm 两数相加 | Add Two Numbers You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a sing…...

废柴勇士(据说没有人能坚持37秒)

欢迎来到程序小院 废柴勇士 玩法&#xff1a;点击屏幕下方左右按键击杀怪物&#xff0c;怪物会在左右方向同时来袭&#xff0c;快速点击按钮进行击杀怪物&#xff0c;看您能够坚持多少秒&#xff0c; 据说还没有能够坚持37秒&#xff0c;快去击杀怪物挑战吧^^。开始游戏https:…...

buuctf_练[羊城杯2020]easyphp

[羊城杯2020]easyphp 文章目录 [羊城杯2020]easyphp掌握知识解题思路关键paylaod 掌握知识 ​ .htaccess文件的利用&#xff0c;把自己指定当做 php文件处理&#xff1b;preg_match正则匹配的了解&#xff0c;stristr函数的绕过&#xff1b;file_put_contents文件写入操作的了…...

【Linux】安装配置虚拟机及虚拟机操作系统的安装

目录 一、操作系统 1. 介绍 2. 功能 3. 有哪些 4. 个人版本和服务器版本的区别 二、VMWare虚拟机 1. 安装 2. 配置 三、安装配置Windows Server 1. 配置 2. 安装 四、虚拟机的环境配置及连接 1. 主机连接虚拟机 2. 虚拟机环境配置及共享 3. 环境配置 一、操作系…...

hugo-stack for github

静态博客框架jekyll、hexo和hugo三者之间的区别与差异 博客生成器? 全名为静态网站生成器&#xff0c; 可在任意拥有主机功能的环境下寄存(托管)可直接配合域名进行全球访问 劣势: 每次更新网页必须重新生成整个网站编译速度&#xff08;单位&#xff1a;秒&#xff09; Jek…...

【uniapp】proxy 代理切换至线上测试地址调试接口

本地测试地址形如&#xff1a;http://192.168.124.x:xxxx 线上测试地址形如&#xff1a;https://xxxx.xxxx.com 使用线上地址之后需要修改配置项 secure 为 true const constant require(./src/utils/constant) module.exports {devServer: {proxy: {/api: {target: constan…...

对比Vue2和Vue3的自定义指令

一、自定义指令简介 自定义指令是Vue提供的能力,用于注册自定义的指令,从而实现一些自定义的DOM操作。 二、Vue2中自定义指令 在Vue2中,自定义指令通过全局方法Vue.directive()进行注册: // 注册全局指令v-focus Vue.directive(focus, {inserted: function(el) {el.focus()…...

Python:实现日历到excel文档

背景 日历是一种常见的工具,用于记录事件和显示日期。在编程中,可以使用Python编码来制作日历。 Python提供了一些内置的模块和函数,使得制作日历变得更加简单。 在本文,我们将探讨如何使用Python制作日历,并将日历输出到excel文档中。 效果展示 实现 在代码中会用到cale…...

C++ 异常和错误处理机制:如何使您的程序更加稳定和可靠

在C编程中&#xff0c;异常处理和错误处理机制是非常重要的。它们可以帮助程序员有效地处理运行时错误和异常情况。本文将介绍C中的异常处理和错误处理机制。 什么是异常处理&#xff1f; 异常处理是指在程序执行过程中发生异常或错误时&#xff0c;程序能够捕获并处理这些异常…...

第1章 Java、IDEA环境部署与配置

JavaEE简介与IDE环境部署 课程目录 JavaEE简介JDK环境部署IntelliJ IDEA环境部署 JavaEE简介 1. JavaEE是什么&#xff1f; Java EE&#xff08;Java Platform&#xff0c;Enterprise Edition&#xff09;是sun公司&#xff08;2009年4月20日甲骨文将其收购&#xff09;推…...

如何进行二进制文件的读写操作?

在C语言中&#xff0c;进行二进制文件的读写操作是非常常见的任务&#xff0c;尤其在处理文件、图像、音频和视频等二进制数据时。本文将详细介绍如何进行二进制文件的读写操作&#xff0c;包括如何打开文件、读取文件、写入文件以及关闭文件。我们将使用标准C库中的函数来执行…...

python实现PDF表格与文本分别导出EXCEL

现需将pdf 转换至Excel &#xff0c; 目前实现方式&#xff1a;将PDF的TABLE部分与 非 TABLE部分分别导出至Excel两个sheet中 1&#xff09;、识别PDF中的表格块 2&#xff09;、将PDF转换为Word格式 3&#xff09;、提取Word中非表格的文本数据 4&#xff09;、对文本与表格重…...

Java开发-WebSocket

WebSocket是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工通信-浏览器和服务器只需要完成一次握手&#xff0c;两者之间就可以创建持久性的连接&#xff0c;并实现 双向数据传输。 使用 导入maven坐标 <dependency><groupId>org.springframework.bo…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)

船舶制造装配管理现状&#xff1a;装配工作依赖人工经验&#xff0c;装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书&#xff0c;但在实际执行中&#xff0c;工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

使用LangGraph和LangSmith构建多智能体人工智能系统

现在&#xff0c;通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战&#xff0c;比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...

基于Java+VUE+MariaDB实现(Web)仿小米商城

仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意&#xff1a;运行前…...