我们知道,基于WEBRTC实现的多对多实时音视频互动通信就必须需要搭建信令服务器作为信令转发操作。那么我首先了解一下,什么是webrtc信令服务器?
在webrtc的规范中,其实是没有将信令服务这一块纳入到整个规范当中的。更多的是规范客户端所有的过程。为什么没有纳入到规范中,这是因为各个公司的业务模型都是不一样的。很难将每个公司的信令都并成一套规范。所以这样,还不如让他们自己去定义。只要是我必须的信息能交换,其他的业务,你自己去定义,这样就比较灵活,各个公司就更容易去接受,这其实是对webrtc整个的推广是比较有好处的。
信令服务器的作用:
如果没有信令服务器,各个webrtc之间肯定是不能通信的。
看图,这张图就清晰地表达了信令服务器在整个过程的作用,首先看蓝色部分,一个是发起端,一个是接收端,那么发起端和接收端之前要传输媒体数据的时候,他有两个信息必须要通过信令服务器的相互交换才能实现通信的,那两个信息是什么呢,第一个是媒体信息,这个媒体信息通过什么来表述呢,那就是SDP,这个SDP会在往后的分享会给大家作详细的介绍,可以简单地理解,我们双方需要通信,那么你的编解码器是什么,比如我现在进行视频传输,我的编解码是H264,那么对方也要告诉我你能不能支持h264,这个信息必须要传递的,另外你是否支持音频,是否支持视频,你的编码器是什么,这些信息都是通过SDP协议描述出来,然后通过信令服务器,首先就将这个SDP发送到服务器,然后服务器再中转,再中转到另一端,为什么要通过信令服务器进行中转,这是因为这时候双方还没有建立起连接,相互之间还不知道对方的存在。第二个要传递的是网络信息,大家都知道两个webrtc之间他们会尽可能地选择P2P进行传输,那么在他们进行连接之前,要怎样发现对方呢?那也是通过信令服务器,首先你要将你相关的网络信息传输到信令服务器。那这个信令服务器就帮你交互到另外一端,那这一端拿到你的信息之后,才知道,大家都是处于同一个局域网内,那就直接通过P2P传输就好了,那如果是不同一个局域网内,那么就需要使用P2P穿透,所以这个信令服务器最基础的作用就是一是媒体信息的交换,二是网络信息的交换,再有就是第三个就是我们的具体业务,比如说是加入房间,离开房间,禁言,或者给对方权限发言等,所以这就是整个信令服务器在WEBRTC通信中的作用。
为什么要使用socket.io,其中有几个优点
1. socket.io 是websocket超集,他身本就有websocket的功能,我们都知道在我们进行传输的时候,一般有两个协议,一个是TCP协议,一个是UDP协议,底层协议里面,一般来说UDP是用于流媒体的传输,音频,视频,还有文本,文字的聊天,但UDP的问题在于,他是不可靠的,他会丢包,这个对于音频和视频来说是没有问题的,当网络状况不好的时候,他可以丢包,我丢了一帧数据,他最多就是卡一下,但对于信令来说,他必须是需要可靠的,我们需要我们的数据发送到哪,从哪来的,这些都是需要可靠的传输协议作支撑,他要的是要么完全接收,要么就是完全不接收。所以对于信令来说是必须要使用tcp,而我们的websokcet是使用tcp的,所以socket.io也是使用tcp
2. socket.io有房间的概念,我们来想想,如果我们两个人之间进行通信,我们就必须先要进行一个房间里,我们要开会也好,什么也好,首先要聚集在一起,这是一个虚拟的逻辑概念。我们看过webrtc的demo可以知道,他实际上有三种服务器,第一种是room服务器,第二种就是我们的信令服务器,第三种就是流媒体中转服务器。而我们选用的socket.io他因为本身就具有房间这么一个概念,也具有信令转发这么一个功能,所以我们就无需再另外搭建room服务器和信令服务器,直接使用socket.io就可以了。
3. socket.io跨平台,跨终端,跨语言:我们可以用JS,也可以用JAVA,这样就使我们很方便地在各个终端中使用。
socket.io的工作原理
我们选择了Nodejs中的socket.io进行讲解。首先我们将npm的源换成淘宝的,这样下载的时候会快一点
npm install -g cnpm --registry=https://registry.npm.taobao.org
接下来我们使用cnpm的方式进行安装socket.io库
cnpm install socket.io
使用socket.io发送消息
实际上使用socket.io发送消息是的情况有很多,有10多种,但是我们必须要了解的大概也就是4,5种。我们来一个一个看
1. 给本次连接发消息
socket.emit(),把它理解成send就可以了,当我们的客户端发送一条消息给服务器端,服务器端收到消息之后,返一个callback,举个栗子,就是我要加个房间,然后服务器返回一个提示,你已加入成功。我收到这个提示之后,我就进行其他的操作,这一个过程都是异步的。
2. 给某个房间内所有人发消息。
这种情况相当于一个广播,给在房间内的所有人都发消息,包括我自己。还是以上边的栗子说说,我加入了房间,那么给房间内的所有人发一个消息说,这个人加入进来了。当然有些业务就不需要这样,你加入了就加入了,还有一个就是各个用户端都需要维护一个用户列表。那谁来谁走了,都要清楚,这个时候每个人都要收到这个消息,对于发送者来,我们就可以根据这个消息进行处理,比如音视频的处理。对于其他用户来说,收到了这个用户加入来进来的消息,我就更新一下我的用户列表。将这个用户添加我的用户列表里面去。
它用的是 io.in(room).emit(),这个IO,解释一下,代表整个这个节点的socket里面的所有用户都包含在内,in(room)就是代表节点某个房间内。也有一种写法是io.sockets.in,但这个sockets可写可不写
3. 除了本连接外,给某个房间内所有人发消息。
这种就是,给某个房间内除我自己之外的人发一个消息,比如全体静音,就是不让人说话,只允许我自己说话
使用:
socket.to(room).emit(),to(room)
就是给某个房间内除我自己之外的人发消息
4. 除本连接外,给所有人发消息
socket.broadcast.emit()
跟第三种情况很相似,但,这个是给本人外,这个节点的所有房间发消息。
socket.IO客户端处理消息
当我们客户端收到的处理信息之后,怎样处理。
1. 发送action命令
server: socket.emit(‘action’); // 当服务器发送了个action
client: socket.on(‘action’,function(){}); // 我们的客户端就需要监听这个动作。
2. 发送action命令,还在data数据
server : socket.emit(‘action’,data);
client: socket.on(‘action’,function(data){…});
3. 发送了action命令,还有两个数据
server: socket.emit(action,arg1,arg2);
client: socket.on(‘action’,function(arg1,arg2){…});
4. 发送一个action命令,在emit方法中包含回调函数
server: socket.emit(‘action’,data,function(arg1,arg2){…});
client: socket.on(‘action’,function(data,fn){fn(‘a’,’b’);});
至止,关于使用socket.io搭建简单的信令服务器的教程到这里,下一次本光头将介绍实战中如何应用socket.io。