在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 是构建实时通信应用程序的强大工具,对于任何需要实时通信的项目都值得考虑。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

爬虫进阶-反爬破解7(逆向破解被加密数据:全方位了解字体渲染的全过程+字体文件的检查和数据查看+字体文件转换并实现网页内容还原+完美还原上百页的数据内容)

目录 一、全方位了解字体渲染的全过程 1.加载顺序 2.实践操作&#xff1a;浏览器中调试字体渲染 3.总结&#xff1a; 二、字体文件的检查和数据查看 1.字体文件的操作软件 2.映射关系的建立 3.实践操作&#xff1a;翻找样式和真实内容 4.总结&#xff1a; 三、字体文…

Tp框架如何使用事务和锁,还有查询缓存

1.事务 在ThinkPHP框架中&#xff0c;可以使用think\db\Transaction类来实现事务。 use think\Db; use think\db\Transaction;// 开始事务 Db::startTrans();try {// 执行数据库操作Db::table(user)->where(id, 1)->update([name > John]);// 提交事务Db::commit(); }…

swagger stub https无法访问

有个app的以前别人写的假服务用http访问可以&#xff0c;但是用https去访问就不行 看官方说schema里面配置一个https就可以了但是对我那个server没有用&#xff1a; 官方参考链接&#xff1a; API Host and Base Path 后来领导给我发了个这个&#xff1a; Node.js Express …

解决方法:从客户端(---<A href=“http://l...“)中检测到有潜在危险的 Request.Form 值。

从客户端(-----<A href"http://l...")中检测到有潜在危险的 Request.Form 值。 解决方法&#xff1a;应该是不同的.net Framework版本对代码的校验不同&#xff0c;造成在高版本操作系统&#xff08;即高.net Framework版本校验&#xff09;不兼容&#xff0c;可…

【疯狂Java】数组

1、一维数组 (1)初始化 ①静态初始化&#xff1a;只指定元素&#xff0c;不指定长度 new 类型[] {元素1,元素2,...} int[] intArr; intArr new int[] {5,6,7,8}; ②动态初始化&#xff1a;只指定长度&#xff0c;不指定元素 new 类型[数组长度] int[] princes new in…

自组织映射Python实现

自组织映射&#xff08;Self-organizing map&#xff09;Python实现。仅供学习。 #!/usr/bin/env python3""" Self-organizing map """from math import expimport toolzimport numpy as np import numpy.linalg as LAfrom sklearn.base import…

Vue 项目进行 SEO 优化

SSR 服务器渲染 服务端渲染, 在服务端 html 页面节点, 已经解析创建完了, 浏览器直接拿到的是解析完成的页面解构 关于服务器渲染&#xff1a;Vue 官网介绍 &#xff0c;对 Vue 版本有要求&#xff0c;对服务器也有一定要求&#xff0c;需要支持 nodejs 环境。 优势: 更好的 …

如何避免阿里云对象储存OSS被盗刷

网站app图片的云端存储离不开对象存储oss,而最难为的问题就是app做的出名了&#xff0c;少不了同行的攻击&#xff0c;包含ddos&#xff0c;cc攻击以及oss外链被盗刷&#xff01; 防盗链功能通过设置Referer白名单以及是否允许空Referer&#xff0c;限制仅白名单中的域名可以访…

【嵌入式项目应用】__cJSON在单片机的使用

目录 前言 一、JSON和cJson 二、cJSON是如何表示JSON数据的 三、如何封装完整的JSON数据 1. 先将串口打通&#xff0c;方便电脑查看log日志。 2. 增加cjson.c文件&#xff0c;已经在main.c中 3. 准备打包如下的JSON包 4. 代码部分&#xff0c;先将几个部分初始化指针 …

rust学习——智能指针

智能指针 在各个编程语言中&#xff0c;指针的概念几乎都是相同的&#xff1a;指针是一个包含了内存地址的变量&#xff0c;该内存地址引用或者指向了另外的数据。 在 Rust 中&#xff0c;最常见的指针类型是引用&#xff0c;引用通过 & 符号表示。不同于其它语言&#xf…

量子革新加速!法国量子即服务公司ColibriTD完成100万欧元融资

​&#xff08;图片来源&#xff1a;网络&#xff09; 法国量子即服务初创公司ColibriTD已完成100万欧元的种子轮融资&#xff0c;此次融资由Earlybird-X基金以及一群天使投资人领投&#xff0c;这笔资金将用于开发量子即服务平台。 ColibriTD的创始人有两位。创始人Laurent …

线性代数-Python-03:矩阵的变换 - 手写Matrix Transformation及numpy中的用法

文章目录 一、代码仓库二、旋转矩阵的推导及图形学中的矩阵变换2.1 让横坐标扩大a倍&#xff0c;纵坐标扩大b倍2.2 关于x轴翻转2.3 关于y轴翻转2.4 关于原点翻转&#xff08;x轴&#xff0c;y轴均翻转&#xff09;2.5 沿x方向错切2.6 沿y方向错切2.7 旋转2.8 单位矩阵2.9 矩阵的…

使用el-tree问题之清空勾数据不生效

一、问题场景描述 在做角色菜单按钮权限时&#xff0c;多数采用树结构勾选数据&#xff0c;这里使用了element中的el-tree。如下图&#xff1a; 1、我给角色1勾选了权限列表数据的前三行&#xff0c; 点击弹框的确定 2、紧接着点击角色2的权限按钮&#xff0c;给角色2分配修…

分享一款基于 AI 的 Chrome 插件

最近使用大模型比较多&#xff0c;公司虽然提供了免费的 ChatGPT 但是需要跳转特定页面才能访问&#xff0c;比较麻烦&#xff0c;于是就想到是否可以开发一款类似于有道词典一样的 Chrome 插件&#xff0c;可以在任意页面使用&#xff0c;虽然市面上也有类似的插件&#xff0c…

12.4 组播鼠标批量执行

组播模式相比单播模式可以提高网络的效率和带宽利用率&#xff0c;因为组播数据包只需要发送一次&#xff0c;就可以被多个接收者接收&#xff0c;而不需要每个接收者都单独发送一份数据包。这在需要同时向多个接收者发送相同数据的场景下特别有用&#xff0c;如视频会议、在线…

ubuntu tools

1 cloc calculate lines of your code sudo apt-get install cloccloc ./file

C算法:写一个用于找出数组的最大值和最小值的函数

需求&#xff1a; 写一个用于找出数组的最大值和最小值的函数。 示例&#xff1a;int array[9] {5, 9, 3, 1, 2, 8, 4, 7, 6}; 该数组最大值的下标为1&#xff0c;最小值的小标为3。 代码实现&#xff1a; #include <stdio.h>int getNum(int *array,int len,int (*…

kubernates 集群实战-安装K3s集群

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

【JavaEE重点知识归纳】第11节:认识异常

目录 一&#xff1a;异常的概念和体系结构 1.概念 2.体系结构 3.异常分类 二&#xff1a;异常的处理 1.防御式编程 2.异常的抛出 3.异常的捕获 4.异常的处理流程 三&#xff1a;自定义异常 一&#xff1a;异常的概念和体系结构 1.概念 &#xff08;1&#xff09;在…

ArrayList与List的层级关系及ArrayList解析

List与ArrayList的关系 List List是一个接口&#xff0c;不能直接实例化。如果要使用必须去实例化List的实现类——ArrayList和LinkedList站在数据结构的角度看&#xff0c;List就是一个线性表。常见的线性表&#xff1a;顺序表、链表、栈、队列等 线性表 线性表是n个具有相…