前言我们在学习WebRTC的时候,首先要搭建好实验环境,这样我们就可以在上面做各种实验了。对于WebRTC,它有一套完整的规范,比如如何使用它的接口,如何使用SDP进行媒体协商,如何通过I
前言
我们在学习WebRTC的时候,首先要搭建好实验环境,这样我们就可以在上面做各种实验了。
对于WebRTC,它有一套完整的规范,比如如何使用它的接口,如何使用SDP进行媒体协商,如何通过ICE收集地址和检查连通性等等。除此之外,WebRTC还需要房间服务器聚集多个终端进行管理,需要信令服务器交换信令数据(如媒体描述信息SDP的交换,连接地址的交换和交换等。).但这部分在WebRTC的规范中没有规定,需要用户自己处理。
可以根据自己的喜好选择服务器(比如Apache、Nginx或者Nodejs)。今天,我将介绍如何使用Nodejs构建信令服务器。
你为什么选择Nodejs
Apache、Nginx、Nodejs都是非常成熟的Web服务器,Nginx可以说是性能最好的。但从未来的发展来看,Nodejs可能更有优势。
现在以Chrome为代表的浏览器越来越强大。以前认为不可能通过浏览器实现的事情,现在可以轻松实现。随着H5? WebSocket的出现和WebRTC的加入,人们觉得未来的浏览器无所不能。所以JavaScript语言的发展越来越快。JavaScript技术的流行和各种JS框架的出现可以证明这一点。
Nodejs最大的优势就是可以用js语言开发服务器程序。这样一来,大量的前端学员就可以无缝的转向服务器开发,甚至有可能前后端使用同一套代码。对于这一点,我认为无论对个人还是企业都是一个极大的诱惑。
一方面,JS语言的简单性可以方便开发各种功能的服务器程序。
更有价值的是Nodejs的生态链非常完整,各种功能库。可以根据自己的需求快速安装NPM,这也让它受到开发者的欢迎。
Nodejs现在是一个非常受欢迎的Web服务器。它在服务器端使用V8(JavaScript)引擎,并解析JS脚本来控制服务器的行为。这对于广大的JS同学来说是太幸福了。十年前,很难想象服务器程序可以用JS脚本语言编写。
当然,如果想扩展Nodejs的能力,还是要写C/C++库,加载到Nodejs中。
NodeJS的基本原理
Nodejs的工作原理如上图所示,其核心是V8引擎。通过这个引擎,js可以调用C/C++方法或对象。相反,C/C++也可以访问javascript方法和变量。
Nodejs首先把用JavaScript写的应用交给V8引擎解析。V8理解了应用的语义后,调用Nodejs底层的C/C++ API来启动服务。所以Nodejs的强大之处在于,js可以直接调用C/C++的方法,这样它的能力可以无限扩展。
以一个http服务的开发为例。Nodejs打开监听服务端口后,底层会调用libuv来处理端口的所有HTTP请求。网络事件处理如下图所示:
当网络请求到来时,它将首先被插入到事件处理队列中。Libuv将监控事件队列。当发现事件时,它会首先判断请求。如果是简单的请求,会直接返回响应。如果是复杂请求,从线程池中取一个线程进行异步处理;
线程被处理后,有两种可能:一种是在线程被处理后向用户发送响应;在另一种情况下,如果需要进一步处理,将生成另一个事件并插入事件队列进行处理;事情就是这样不停地发生,从不停止。
两台V8发动机
如上图,我们使用Nodejs后,实际上有两个V8引擎。V8用于在服务器端解析JS应用程序,并启动服务。另一个V8是浏览器中的V8引擎,用来控制浏览器的行为。
对于使用Nodejs的新手来说,很容易产生困惑,因为服务器端至少要放两个js脚本。其中一个是服务器程序,控制Nodejs的行为,由Nodejs的V8引擎解析处理。另一个是客户端程序,由浏览器请求,发送到浏览器,由浏览器中的V8引擎解析。如果你分不清这个,你就有大麻烦了。
安装节点js
我们来看看具体怎么安装Nodejs。
安装Nodejs非常简单:
在Ubuntu系统下执行:
apt install nodejs
或者在Mac系统下:
brew install nodejs
通过以上步骤,我们已经安装了Nodejs。我这里安装的Nodejs的版本是:v8.10.0。
安装NPM
除了安装Nodejs,我们还需要安装NPM(Node Package Manager),它是Nodejs的包管理器。就像Ubuntu中的apt命令或者Mac中的brew命令一样,专门用来管理各种依赖库。
在它们出现之前安装一个包对我们来说特别麻烦。以Linux为例。假设您想要安装一个工具。其基本步骤是:
先下载这个工具的源代码。
执行。/configure生成生成文件。
执行make命令来编译它。
最后,执行make install将其安装在指定的目录中。
如果在编译过程中发现了依赖库,那么前四个步骤应该在依赖库上执行,即首先安装依赖库,然后安装工具。
你可以看到以前在Linux下安装一个程序或者工具有多麻烦。
Linux有了apt之后,一切都变得简单了。我们要做的就是执行apt install xxx,它会帮你完成上面的操作。
Nodejs的安装包也是如此。NPM相当于Linux下的apt,它的出现大大提高了人们的工作效率。
NPM的安装就像Nodejs的安装一样简单:
在Ubuntu下执行:
apt install npm
或者在Mac下:
brew install npm
socket.io
这次我们使用Nodejs下的socket.io库来实现WebRTC信令服务器。Socket.io特别适合开发WebRTC的信令服务器。通过它搭建信令服务器特别简单,主要是因为它内置了* *房* *的概念。
上图是socket.io和Nodejs的逻辑关系,逻辑非常简单。Socket.io分为两部分:服务器和客户端。服务器在Nodejs加载后监听服务端口。如果客户端要连接服务器,首先要加载socket.io的客户端库,然后调用` io . connect();“它与服务器相连。
需要特别强调的是socket.io消息的发送和接收。Socket.io发送消息的方式有很多,其中最常见的有以下几种,我们必须掌握:
向此连接发送消息。
socket.emit()
向房间中的每个人发送消息。
io.in(room).emit()
向房间中除此连接之外的所有人发送消息。
socket.to(room).emit()
向除此连接之外的所有人发送消息。
socket.broadcast.emit()
如何接收消息?
发送命令命令命令
S: socket.emit('cmd’);C: socket.on('cmd',function(){...});
用数据data发送了一个command命令。
S: socket.emit('action', data);C: socket.on('action',function(data){...});
Command命令发出后,有两段数据。
S: socket.emit(action,arg1,arg2);C: socket.on('action',function(arg1,arg2){...});
有了以上知识,我们就可以实现信令数据通信了。
设置信令服务器
接下来我们来看看如何在Nodejs下通过socket.io搭建服务器:
这是客户端代码,即在浏览器中执行的代码。index.html:
<!DOCTYPE html><html> <head> <title>WebRTC client</title> </head> <body> <script src='/socket.io/socket.io.js?x83982'></script> <script src='js/client.js'></script> </body></html>
代码很简单,就是在主体中引入了两个JS代码。其中socket.io.js用于与服务器建立套接字连接。client.js的作用是做一些业务逻辑,最后通过socket与服务器通信。
首先在server.js目录下创建js的目录,然后在js目录下生成client.js。
以下是client.js的代码:
var isInitiator;room = prompt('Enter room name:'); //弹出一个输入窗口const socket = io.connect(); //与服务端建立socket连接if (room !== '') { //如果房间不空,则发送 "create or join" 消息 console.log('Joining room ' + room); socket.emit('create or join', room);}socket.on('full', (room) => { //如果从服务端收到 "full" 消息 console.log('Room ' + room + ' is full');});socket.on('empty', (room) => { //如果从服务端收到 "empty" 消息 isInitiator = true; console.log('Room ' + room + ' is empty');});socket.on('join', (room) => { //如果从服务端收到 “join" 消息 console.log('Making request to join room ' + room); console.log('You are the initiator!');});socket.on('log', (array) => { console.log.apply(console, array);});
在这段代码中:
首先,弹出一个输入框,要求用户填写要加入的房间。然后通过io.connect()与服务器建立连接,根据socket返回的消息做不同的处理:
房间爆满时的情况;
收到房间空“空”时的情况;
加入“加入”时的情况接收;
以上是在客户端(即浏览器)执行的代码。让我们来看看服务器的处理逻辑:
服务器端代码,server.js:
const static = require('node-static');const http = require('http');const file = new(static.Server)();const app = http.createServer(function (req, res) { file.serve(req, res);}).listen(2013);const io = require('socket.io').listen(app); //侦听 2013io.sockets.on('connection', (socket) => { // convenience function to log server messages to the client function log(){ const array = ['>>> Message from server: ']; for (var i = 0; i < arguments.length; i++) { array.push(arguments[i]); } socket.emit('log', array); } socket.on('message', (message) => { //收到message时,进行广播 log('Got message:', message); // for a real app, would be room only (not broadcast) socket.broadcast.emit('message', message); //在真实的应用中,应该只在房间内广播 }); socket.on('create or join', (room) => { //收到 “create or join” 消息 var clientsInRoom = io.sockets.adapter.rooms[room]; var numClients = clientsInRoom ? Object.keys(clientsInRoom.sockets).length : 0; //房间里的人数 log('Room ' + room + ' has ' + numClients + ' client(s)'); log('Request to create or join room ' + room); if (numClients === 0){ //如果房间里没人 socket.join(room); socket.emit('created', room); //发送 "created" 消息 } else if (numClients === 1) { //如果房间里有一个人 io.sockets.in(room).emit('join', room); socket.join(room); socket.emit('joined', room); //发送 “joined”消息 } else { // max two clients socket.emit('full', room); //发送 "full" 消息 } socket.emit('emit(): client ' + socket.id + ' joined room ' + room); socket.broadcast.emit('broadcast(): client ' + socket.id + ' joined room ' + room); });});
服务器中引入了node-static库,使服务器具有发布静态文件的功能。服务器有了这个功能后,当客户端(浏览器)向服务器发出请求时,服务器通过这个模块获取客户端(浏览器)运行的代码,也就是我们上面说的index.html和client.js,并发送给客户端(浏览器)。
服务器监听端口2013,并相应地处理不同的消息:
–当服务器接收到message消息时,它将直接广播该消息,所有连接到服务器的客户端都将接收到该广播消息。
–当服务器收到“创建或加入”消息时,它会统计房间内的人数,如果房间内没有人,则发送“已创建”消息;如果房间里有一个人,发送“加入”消息和“已加入”消息;如果有两个人以上,就发“满”的信息。
要运行这个程序,您需要使用NPM安装socket.io和node-static。安装方法如下:
转到server.js所在的目录,然后执行以下命令。
npm install socket.ionpm install node-static
启动服务器并测试它
通过以上步骤,我们已经使用socket.io构建了一个服务器,现在我们可以使用以下命令启动服务:
node server.js
如果在这台机器上设置了服务,可以在浏览器中输入localhost:2013,然后创建一个新的选项卡,再次输入localhost:2013。此时,打开控制台看看发生了什么?
在Chrome下,你可以使用Command-Option-J或者Ctrl-Shift-J的DevTools来访问控制台。
摘要
上面我介绍了Nodejs的工作原理,Nodejs的安装部署,以及如何用sokcet.io Socket构建WebRTC信令消息服务器,io因为房间的概念,和WebRTC非常匹配。用它开发WebRTC信令服务器非常方便。
另外,本文中的例子只是一个简单的例子,并没有太大的实用价值。在接下来的文章中,我将以这个例子为基础,给它增加一些功能。最后,你会看到一个完整的演示程序。