首发于 Jhuster 的专栏-音视频
WebRTC 开发实践:如何实现 SFU 服务器

WebRTC 开发实践:如何实现 SFU 服务器

上一篇文章 《WebRTC 开发实践:为什么你需要 SFU 服务器》我们了解了 WebRTC SFU 服务器的基本原理和必要性,解决了 What 和 Why,本文则更近一步,探究一下实现 SFU 服务器的关键技术点有哪些 ?重点解决一下 How

1 什么是 SFU ?

首先,我们再看一次 SFU 服务器的定义,什么是 SFU ?

SFU 的全称是:Selective Forwarding Unit,是一种路由和转发 WebRTC 客户端音视频数据流的服务端程序。

如图所示,SFU 服务器最核心的功能就是与每一个 WebRTC Peer 客户端建立链接,分别接收来自他们的音视频数据,并实现 one-to-many 的能力(即把一个客户端的流转发到其他 WebRTC Peer 客户端),那么,如果我们要实现这样一台 SFU 服务器,有哪些需要解决和处理的问题呢 ?

我们可以想象一下 Web 服务器和直播服务器的工作原理,浏览器/直播客户端,要想完成与服务器之间的数据交换,通常离不开如下几个步骤:

1. 通过 DNS 解析,拿到服务器的 IP 地址;然后通过 “约定” 的端口(如:80 或者 1935)连接到服务器
2. 客户端使用 “约定” 的信令协议(如:HTTP,RTMP),发送请求给服务器,实现数据交换的准备工作
3. 客户端开始上行数据给服务器,或者服务器开始下发数据到客户端,结束后,通过信令关闭连接
4. 静态的资源型的数据(文件、网页),通常服务端是读取磁盘上的数据拷贝一份给需要的客户端
5. 非静态的实时数据(如:直播流),服务器则通过在 “内存” 中拷贝并转发给需要的客户端

同样,WebRTC 客户端与 SFU 服务器之间的交互,也是离不开这些步骤的,特别是 4/5,其实就是所谓的 one-to-many 能力。

2 信令和传输通道的建立

首先我们解决第一个问题,即 WebRTC 客户端是如何跟 SFU 服务器建立数据传输通道的 ?

如图,我们先看看浏览器与 Web 服务器的建联过程:浏览器通过 DNS 解析 URL 中的域名,拿到 IP 后通过 80 端口连接上服务器(后续的数据传输均复用这条 TCP 链路)。

WebRTC 其实也是类似的,但是与标准的 HTTP 服务或者 RTMP 直播服务相比,还是有些区别的,如下:

1. 信令和数据通道是 “分离” 的,信令目前没有统一的实现方案,可以使用任何方案(如:HTTP、TCP 自定义协议、SIP 等等),但是数据并不走这条信令链路,而是走单独的 UDP 端口
2. 数据通道使用的 UDP 协议,不像 TCP 有 “连接” 的概念,客户端仅仅知道服务器的 UDP 端口,但不 “连接” 是无法预判传输通道是否真的 OK(主要是部分 NAT 网关类型的限制,导致并不是所有 UDP 传输都能通),因此需要借助一些框架和协议来判断 UDP 通道的可用性(即 ICE 协议)

上述内容分析完了,我们就可以看看如何实现 SFU 的信令和传输通道了:

1. 实现 HTTP Web Server 服务(或者 SIP 或者基于 TCP 自定义协议),用于提供 “信令” 的支持(如:推流命令、拉流命令等)
2. 通过 libnice 库或者自己 coding 的方式,实现 ICE 协议,用于提供 UDP “数据通道” 的检测和建联
3. 实现 UDP 数据监听和发送,用于接收客户端的数据,转发其他客户端的数据

3 需要实现哪些 “信令” ?

对于 HTTP 协议,实现的 “信令” 包括:GET,POST,DELETE 等等,定义了浏览器期望进行的行为。同理,对于 SFU,我们也要定义一系列必要的信令,以约定客户端和服务器对应的行为,那具体有哪些呢 ?

其实 WebRTC 客户端,与 SFU 服务器需要协商的事情,无外乎就是如下几点:

1. ICE 建联:交换 ICE 信息(用户名、密码、IP 地址、UDP 端口等)
2. 发布流/取消发布流:客户端通知服务器准备好接收数据
3. 订阅流/取消订阅流:客户端通知服务器准备好转发数据

因此,SFU 服务器通过任意一种方式(HTTP/TCP 等),提供 ICE Connection,Publish,Subscribe 信令即可,SFU 在信令背后需要实现的逻辑分别如下:

1. ICE Connection:添加一路 UDP 通道
2. Publish:添加一个逻辑上的数据 Producer,通过 UDP 通道 recv 客户端的数据,通知逻辑上的 Consumers
3. Subscribe:添加一个逻辑上的数据 Consumer,收到 Producer 通知后,通过 UDP 通道 send 给客户端

4 如何实现 one-to-many ?

这是 SFU 最核心的功能,其实也不是 WebRTC SFU 特有,如前面所述,凡是非静态资源型的服务(数据实时产生实时消费)均需要在服务端实现 one-to-many,比较典型的例子就是 RTMP 直播流服务器,需要将客户端推流上来的数据,实时转发给多个拉流的客户端。

实现 one-to-many ,最重要的一点是需要把数据的生产者(Publisher)和数据的消费者(Subscriber)关联起来,怎么关联呢 ?

WebRTC 传输的音视频数据,实际上是封装在 RTP 包里面,RTP 包头有个很重要的字段,叫做 SSRC(同步源标识),就是这路流的唯一标识,如图:

数据的生产者(Publisher)和数据的消费者(Subscriber)即可通过 SSRC 来关联,实现 one-to-many 的核心代码逻辑抽象如下:

即:当 SFU 接收到 Publisher 发送上来的数据后,轮询一下所有的 Subscribers,如果 SSRC 匹配成功,则将数据转发给这个客户端。

5 数据传输协议

WebRTC 采用的是标准的 RTP/RTCP 协议进行数据的封包和网络状态反馈,因此,SFU 服务器也需要支持 RTP/RTCP 的封包和解包,从而能够 “理解” 客户端的 UDP 数据包的含义,如:提取出 SSRC 或者 timestamp 等必要的信息,也能及时地向客户端反馈网络状态(RTCP)。

关于 RTP/RTCP 传输协议,已经发展多年,是比较成熟的多媒体传输协议了,也有很多不错的开源库,这里就不再赘述了。

6 小结

以上就是关于如何实现 SFU 服务器最核心的知识点了,暂且就分享到这里了,如有疑问的小伙伴欢迎来信 lujun.hust@gmail.com 交流。另外,也欢迎大家关注我的新浪微博 @卢_俊 或者 微信公众号 @Jhuster 获取最新的文章和资讯。

玻璃钢生产厂家黄石玻璃钢装饰造型生产厂家贵州玻璃钢公仔雕塑厂家阳江玻璃钢装饰工程定做香港商业美陈厂重庆玻璃钢家具生产厂家河池玻璃钢种植池厂铜川玻璃钢花坛公司吴忠不锈钢雕塑厂家滁州玻璃钢产品批发威海玻璃钢前台公司眉山玻璃钢树池坐凳哪家好黄冈玻璃钢制品制作赣州不锈钢花盆多少钱滁州玻璃钢种植池厂家直销邯郸不锈钢家具多少钱朔州玻璃钢外壳批发澳门玻璃钢定做松原玻璃钢花钵公司鹰潭玻璃钢花池多少钱阜新商场美陈批发安顺玻璃钢座椅制造宿迁玻璃钢座椅多少钱荆州玻璃钢种植池厂家直销湖州玻璃钢造型制造山东玻璃钢餐桌椅厂三明玻璃钢装饰工程定制合肥玻璃钢人物雕塑厂珠海玻璃钢餐桌椅厂衢州玻璃钢花钵厂家铜陵玻璃钢产品加工香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声卫健委通报少年有偿捐血浆16次猝死汪小菲曝离婚始末何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言男子被猫抓伤后确诊“猫抓病”周杰伦一审败诉网易中国拥有亿元资产的家庭达13.3万户315晚会后胖东来又人满为患了高校汽车撞人致3死16伤 司机系学生张家界的山上“长”满了韩国人?张立群任西安交通大学校长手机成瘾是影响睡眠质量重要因素网友洛杉矶偶遇贾玲“重生之我在北大当嫡校长”单亲妈妈陷入热恋 14岁儿子报警倪萍分享减重40斤方法杨倩无缘巴黎奥运考生莫言也上北大硕士复试名单了许家印被限制高消费奥巴马现身唐宁街 黑色着装引猜测专访95后高颜值猪保姆男孩8年未见母亲被告知被遗忘七年后宇文玥被薅头发捞上岸郑州一火锅店爆改成麻辣烫店西双版纳热带植物园回应蜉蝣大爆发沉迷短剧的人就像掉进了杀猪盘当地回应沈阳致3死车祸车主疑毒驾开除党籍5年后 原水城县长再被查凯特王妃现身!外出购物视频曝光初中生遭15人围殴自卫刺伤3人判无罪事业单位女子向同事水杯投不明物质男子被流浪猫绊倒 投喂者赔24万外国人感慨凌晨的中国很安全路边卖淀粉肠阿姨主动出示声明书胖东来员工每周单休无小长假王树国卸任西安交大校长 师生送别小米汽车超级工厂正式揭幕黑马情侣提车了妈妈回应孩子在校撞护栏坠楼校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变老人退休金被冒领16年 金额超20万西藏招商引资投资者子女可当地高考特朗普无法缴纳4.54亿美元罚金浙江一高校内汽车冲撞行人 多人受伤

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化