当前位置: 主页 > 前端开发

web后端开发-web 前端 后端 开发

发布时间:2023-02-11 14:24   浏览次数:次   作者:佚名

推荐先阅读:WEBRtc实现视频会议-今日头条(头条网)

https://www.toutiao.com/article/7164302481869210152/

我们已经解释了WebRTC的基本原理,以及被投递端和投递发起者的交互过程。 本节将构建服务器。 我将使用 node.js 作为后端。

你可能需要提前了解以下知识:socket.io实现的websocket、nodejs server express框架、WebRTC交互流程、TURN/STUN server。

服务器主要由两部分组成:信令服务器和TURN/STUN服务器。 当然,它们可以运行在同一台主机上。

关于 WebSocket 和 Socket.IO 的信令服务器聊天

简单来说:websocket是一种让服务端主动向客户端推送消息的技术。

在常见的项目中,往往是前端发起请求,后端响应的模型。 如果后端需要主动推送信息,往往会用到轮询。 大多数这种大规模轮询都是对性能的无意义浪费。 websocket 标准允许客户端与服务器建立长连接。 连接成功后,可以进行全双工通信,即服务端可以主动向目标客户端推送信息。

为什么我们在 WebRTC 中需要 WebSocket?

keyboard_arrow_down

Socket.IO 是一个 node.js 库。 用于在后端建立一个WebSocket服务。 您可以像这样将其加载到支持 Express 的服务器上:

//  若你需要在同一端口监听socket和express请求,可以用这种写法
// 引入node包
const express = require('express');
const socketio = require('socket.io');
// 创建express和http后端
const app = express();
const http = require('http');
// 绑定express的http服务
const server = http.createServer(app);
// 把socket.io绑定到http服务器上
const io = socketio(server, { cors: true });
server.listen(80);
// 当然,若你不在意还要用express搭建其他的后端逻辑,只需要socket而已,上面的都不需要,可以用
const io = require('socket.io')(80);
//  直接搞定

以后可以使用io来处理WebSocket事件。 常用命令如:

io.of('NAMESPACE').on('connection', (socket) => {
    socket.on('YOUR_EVENT',(arg1,arg2,...)=>{

web后端开发_web后端开发是干什么_web 前端 后端 开发

// YOUR_CODE_HERE }); socket.join(ROOM_NAME); io.to('abc').emit('EVENT',args); socket.broadcast.emit('EVENT',args); socket.broadcast.to('ROOM').emit('EVENT',...args); });

有关 socket.io 的更多信息,请参阅官方文档。

为什么我创建socket时请求socket.io?DIO=xxxx,返回404?

keyboard_arrow_down

信令服务器建设

在下面的代码讲解中web后端开发,我将从三端代码(发起投射端、信令服务器、投射端)开始,一步步实现信令服务,因为websocket更像是几个人之间的“对话” ,请注意每段代码属于三个端点中的哪一端?

// 被投屏端,向信令服务器注册,等待连接。
import io from "socket.io-client"
let socket = io.connect('YOUR_SOCKET_SERVER');
socket.on('connect',function()=>{ // 保留事件,连接成功触发
    socket.emit('TV_INIT'); // 触发TV_INIT事件,可以在参数传token之类的校验。
});

// 信令服务器端
// 外面的io.on就在这写一次,以后信令服务器的socket监听直接都扔io.on里面就行
io.on('connection',(socket)=>{
    socket.on('TV_INIT',function(){
        // 你的代码,生成投屏码projCode
        socket.join(projCode); // 加入房间
        socket.emit('TV_INIT_OK',projCode); // 返回投屏码
    })
});

web后端开发是干什么_web后端开发_web 前端 后端 开发

// 被投屏端
socket.on('TV_INIT_OK',(code)=>{
    // 拿到投屏码code,显示出来。
})

接下来是WebRTC的服务流程

// 发起投屏端
// 拿到输入的投屏码,加入房间
socket.emit('JOIN_ROOM',projCode);// 也可以在这时候做用户的身份校验

// 信令服务器
socket.on('JOIN_ROOM',projcode=>{
    // 保存socket和它的projcode,可以用一个对象
    socket.join(projcode); // 加入房间
})

// 发起投屏端
// 生成PeerConnection的Offer,发送给信令服务器转发
socket.emit('CLIENT_OFFER_TO_SERVER',offer);

// 信令服务器
socket.on('CLIENT_OFFER_TO_SERVER',offer=>{
     // 向被投屏端转发offer,利用broadcast直接在房间里广播。ROOM是之前加入房间的时候保存的
     socket.broadcast.to(ROOM).emit('CLIENT_OFFER_TO_TV',offer);
});

// 被投屏端
socket.on('CLIENT_OFFER_TO_TV',offer=>{
    // 被投屏端拿到了offer,创建Answer,按照相同的方法返回。
})

兑换优惠的方法如上。 但是根据WebRTC规范,还需要实现ICE信息交换(ICECandidateExchange)。 也可以采用类似的思路,但是要注意emit ICE交换事件的时机。 建议放在onicecandidate事件中,从事件回调中获取ice candidate。 转移。

// 发起投屏端
peerConnection.onicecandidate = function (event) {
          console.log(event);

web后端开发_web后端开发是干什么_web 前端 后端 开发

if (event.candidate) { socket.emit("RTC_Candidate_Exchange", { iceCandidate: event.candidate, }); } };

// 投屏端
socket.on("RTC_Candidate_Exchange", async (message) => {
      if (message.iceCandidate) {
        try {
          await peerConnection.addIceCandidate(message.iceCandidate);
        } catch (e) {
          console.error("Error adding received ice candidate", e);
        }
      }
    });

警告必须实施 ICE 候选交换

ICE 候选人的交换必须实施,否则可能会出现无法建立 P2P、无法进行屏幕投射或只能进行内网投射等问题。 如果您发现日志中没有触发ICE候选采集事件,请检查您的Offer生成和兑换流程。 我遇到的原因是因为在createOffer之前没有加载流(可能导致系统认为没有数据传输?)最简单的检查方法是在console.log中打印你的Offer,你的offer应该是一个特别的长字符串(至少 20 行或更多)

实施这些后,如果您的 TURN/STUN 服务器设置正确(当 new RTCPeerConnection(config) 正确时传入的配置),屏幕投射应该立即开始! 恭喜!

TURN/STUN 服务器设置

然而,我们还有其他事情要做:设置我们自己的 TURN/STUN 服务器。

这部分非常复杂。 幸运的是,大名鼎鼎的谷歌开源了一个解决方案:Coturn

GitHub

转轮/转轮

coturn TURN 服务器项目

★ 8.4k

网上有很多关于Coturn部署的教程web后端开发,可以看下面这篇文章

获取页面信息时出现问题

尝试直接访问

补充几点:

web后端开发_web后端开发是干什么_web 前端 后端 开发

coturn数据库路径:/usr/local/var/db/turndb

Coturn配置文件路径:/usr/local/etc/turnserver.conf

这里补充一下认证相关的东西,感觉相关的资料挺少的。 如何使用coturn服务器认证和配置tls访问?

打开coturn的配置文件,添加:

external-ip=公网ip
user=你的user
realm=你添加的realm
lt-cred-mech
cert=证书位置
pkey=证书位置
use-auth-secret
static-auth-secret=自己随便设

其中,static-auth-secret是指自己指定静态密钥,而不是从coturn数据库中的turn-secret表中查找密钥。

那么,我们如何生成链接服务器需要的用户名和密码呢?

官方规则非常简单。 用户名是“过期时间:用户名”的字符串拼接,其中用户名可以是任意值,不需要事先注册。 如果要创建系统,可以使用原始系统的用户名。 密码是用sha1加密的base64格式的密码。 如果开启use-static-secret,coturn会直接使用用户名和你设置的密钥进行加密,然后与你的密码进行比对。 也就是说,如果密钥被泄露,密码就等于没有。 如果不设置,coturn会使用turn-secret数据表中的secret来尝试一一比较,应该是为了提高安全性。

用户认证后可以返回turn的登录信息,如果用js可以这样写

// 安全提示:你应该在后端运行这些代码而不是在客户端!!!
const crypto=require('crypto');
function getKey(username) {
// 如果你在配置文件开启了use-static-secret,则直接填写你在那里写的密钥
        let request_key = '你的密钥';
// 过期时间戳,超过时间戳密钥无效。
        let time = (Date.now() + 365 * 1 * 1000 * 60 * 60 * 24).toString();
        let uname = time + ':' + username;
        let hmac = crypto.createHmac("sha1", request_key);
        let result = hmac.update(uname).digest("Base64");
        return {
            username: uname,

web后端开发_web 前端 后端 开发_web后端开发是干什么

credential: result } } // 生成的config再通过socket回传给客户端,客户端用此作为config创建PeerConnection let key=getKey(用户名); // 发送配置 socket.emit("CONFIG_FEEDBACK", { config: { iceServers: [ { urls: "turn:你的turn服务器:3478?transport=udp", username: key.username, credential: key.credential, }, { urls: "turn:你的turn服务器:3478?transport=tcp", username: key.username, credential: key.credential, }, { urls: "stun:你的stun服务器:3478" }, ], } });

如何测试我的 TURN/STUN 服务器是否成功?

keyboard_arrow_down

关于端口的警告

TURN/STUN服务器的默认端口是3478,但实际上中继时可能会用到大量的高阶端口。 建议在系统防火墙和云服务提供商安全组放行所有TCP和UDP的出站流量。

至此,服务器就搭建好了,可以愉快的投屏啦!

web后端开发是干什么_web后端开发_web 前端 后端 开发