下图描绘了通过 TURN 服务器实现 P2P 数据传输 。
文章插图
CoTurn 是一款免费开源的 TURN 和 STUN 服务器 , 可以到 GitHub 上下载源码编译安装 。
二、信令服务器通信双方彼此是不知道对方的 , 但是它们可以先与信令服务器(Signal Server)连接 , 然后通过它来互传信息 。
可以将信令服务器想象成一个中间人 , 由他来安排两端进入一个房间中 , 然后在房间中可以他们就能随意的交换手上的情报了 。
本文会通过 Node.js 和 socket.io 实现一个简单的信令服务器 , 完成的功能仅仅是用于实验 , 保存在 server.js 文件中 。
如果对 socket.io 不是很熟悉 , 可以参考我之前分享的一篇博文 , 对其有比较完整的说明 。
1)HTTP 服务器
为了实现视频通话的功能 , 需要先搭建一个简易的 HTTP 服务器 , 挂载静态页面 。
注意 , 在实际场景中 , 这块可以在另一个项目中执行 , 本处只是为了方便演示 。
const http = require('http');const fs = require('fs');const { Server } = require("socket.io");// HTTP服务器const server = http.createServer((req, res) => {// 实例化 URL 类const url = new URL(req.url, 'http://localhost:1234');const { pathname } = url;// 路由if(pathname === '/') {res.writeHead(200, { 'Content-Type': 'text/html' });res.end(fs.readFileSync('./index.html'));}else if(pathname === '/socket.io.js') {res.writeHead(200, { 'Content-Type': 'application/javascript' });res.end(fs.readFileSync('./socket.io.js'));}else if(pathname === '/client.js') {res.writeHead(200, { 'Content-Type': 'application/javascript' });res.end(fs.readFileSync('./client.js'));}});// 监控端口server.listen(1234);在上面的代码中 , 实现了最简易的路由分发 , 当访问 http://localhost:1234 时 , 读取 index.html 静态页面 , 结构如下所示 。
<video id="localVideo"></video><button id="btn">开播</button><video id="remoteVideo" muted="muted"></video><script src="https://www.huyubaike.com/biancheng/socket.io.js"></script><script src="https://www.huyubaike.com/biancheng/client.js"></script>socket.io.js 是官方的 socket.io 库 , client.js 是客户端的脚本逻辑 。
在 remoteVideo 中附带 muted 属性是为了避免报错:DOMException: The play() request was interrupted by a new load request 。
最后就可以通过 node server.js 命令 , 开启 HTTP 服务器 。
2)长连接
为了便于演示 , 指定了一个房间 , 当与信令服务器连接时 , 默认就会被安排进 living room 。
并且只提供了一个 message 事件 , 这是交换各端信息的关键代码 , 将一个客户端发送来的消息中继给其他各端 。
const io = new Server(server);const roomId = 'living room';io.on('connection', (socket) => {// 指定房间socket.join(roomId);// 发送消息socket.on('message', (data) => {// 发消息给房间内的其他人socket.to(roomId).emit('message', data);});});因为默认是在本机演示 , 所以也不会安装 CoTurn , 有兴趣的可以自行实现 。
三、客户端在之前的 HTML 结构中 , 可以看到两个 video 元素和一个 button 元素 。
const btn = document.getElementById('btn');// 开播按钮const localVideo = document.getElementById('localVideo');const remoteVideo = document.getElementById('remoteVideo');const size = 300;在两个 video 元素中 , 第一个是接收本地的音视频流 , 第二个是接收远端的音视频流 。
经验总结扩展阅读
- 从 Wepy 到 UniApp 变形记
- 房贷还款记录需要保存吗 房贷提前还款怎么支付
- 之六 2流高手速成记:从SpringBoot到SpringCloudAlibaba
- 电脑开不了机怎么办简单方法(笔记本电脑开不了机)
- Windows下自动云备份思源笔记到Gitee
- 2 我的牙套日记
- windows启动不了开不了机怎么办(笔记本无法启动windows)
- 电脑运行了但开不了机怎么办(笔记本电脑冻了一晚开不了机)
- 记录在linux上单机elasticsearch8和kibana8
- 海鲜菇忘记焯水就炒了能吃吗