聊聊 WebRTC 网关服务器1:如何选择服务端端口方案?

neteaseim 2019-06-27

《聊聊 WebRTC 网关服务器》系列文章系由 WebRTCon2018 中网易云信音视频技术专家的分享内容《从零开始构建音视频网关服务器》整理而成,该系列文章将和大家分享网易 NRTC 在 WebRTC 网关项目的自研过程中遇到的一些问题,以及我们最终的解决方法。

《聊聊 WebRTC 网关服务器》第一篇文章将和大家分享如何选择服务端的端口方案。

标准 WebRTC 连接建立流程

在讨论如何选择服务器端的端口方案前,我们先来看看标准 WebRTC 的连接建立流程,这为我们理解这篇文章后续内容提供最基础的知识。

聊聊 WebRTC 网关服务器1:如何选择服务端端口方案?
这里描述的是 Trickle ICE 过程,并且省略了通话发起与接受的信令部分。流程如下:

  1. WebRTC A 通过 Signal Server 转发 SDP OFFER 到 WebRTC B。WebRTC B 做完本地处理以后,通过 Signal Server 转发 SDP ANSWER 到 A。
  2. A、B 同时向 STUN Server 发送 Binding request 请求自身的外网地址,并从 STUN Server 回包的 MAPPED-ADDRESS 中得到各自的外网地址;
  3. A、B 收集完内外网 ICE Candidate,并通过 Signal Server 发送给对方;
  4. 双方开始做 NAT 穿越,互相给对方的 ICE Candidate 发送 STUN Binding Request;
  5. NAT 穿越成功,A、B 之间的 P2P 连接建立,进入媒体互通阶段。在这个过程中,我们看到了有三个核心的部分,SDP 协商、ICE Candidate 交换、Stun Binding Req/Res 的连通性检查。

WebRTC网关连接建立流程

在了解了标准 WebRTC 的建连流程以后,我们来看看 WebRTC 客户端如何与网关建连。

聊聊 WebRTC 网关服务器1:如何选择服务端端口方案?

首先,我们网关的 Media Server 拥有公网 IP,因此 Server 就不需要通过 Stun Server 收集自身的公网 IP。WebRTC 客户端先与网关 Signal Server 协商 SDP,包括 ICE Candidate,Media Server 分配 IP 和端口作为网关的 ice candidate 发送给客户端。因为网关是公网 IP,所以客户端向这个 IP 发送 STUN Binding Request 会被服务器收到, 并回复 Response。接着客户端与网关媒体服务器进行 DTLS 握手与秘钥协商,在此基础上进一步进行 SRTP 的音视频通信。至此,WebRTC 客户端与网关服务器建连成功。
好的,现在我们已经具备了探讨服务器端端口选择的基础知识,接下来我们来看看具体有哪些方案。

WebRTC 网关服务器媒体架构

聊聊 WebRTC 网关服务器1:如何选择服务端端口方案?

最简的服务器端端口方案是我们可以为每个客户端分配一个端口,服务器上使用这个端口区分每个用户,就像图里描述的 A、B、C、D 四个人在 WebRTC 网关服务器上分别对应 UDP 端口 10001~1004。这种方案逻辑上很简单,很多开源的服务器都采用这个方案,如 janus。另外一个原因是使用了 libnice 库在服务器上来和客户端做 ice 建连,类似的做法都是采用多端口的架构。
那么多端口有什么不足呢?

  1. 很多的网络出口防火墙对能够通过的 UDP 端口是有限制的;
  2. 对于服务端来说开辟这么多端口,安全性本身也有一定的问题,特别是网易的运维同学,更是拒绝;
  3. 开辟这么多的端口在 Server 端上,端口的开销和性能均有一定的影响。那能否用单端口?使用单端口前,核心要解决的一个问题是:如何区分每一个 RTP/RTCP 包是属于哪一个 WebRTC 客户端。

为了解决这个问题,我们需要使用一些小技巧。首先,有几个基础知识点我们先了解一下。如下图:

聊聊 WebRTC 网关服务器1:如何选择服务端端口方案?

  1. SDP offer 和 answer 里配置的 ice-ufrag 字段里面内容,原来是用来作为stun数据包的鉴权的,因此 STUN Binding Request 里面的 USERNAME 字段就是由上 Offer 和 answer 的 ice-ufrag 内容拼接而成。
  2. 发送 STUN Binding Request 的客户端本地 udp fd,与 ice 建连成功后发送媒体数据的 udp fd 是同一个,也就是说 Server 上看到的 ip port 是同一个。

有了上面的背景知识,聪明的你们肯定已经大致有一个方案了。我们来看看实现细节是怎么样的:

  1. 在服务器给 Web 端的 SDP Answer 中设置 ice-ufrag 为roomid/userid,其中 RoomID 和 UserID 是通话业务层分配的内容,用于区分每通通话以及参与这。接着做 Ice candidate 协商,Web端开始做连通性检测,也就是 stun binding request 里的USERNAME 为 SDP local 和 remote 的 ice-ufrag 指定内容。
  2. 服务器收到 stun binding request 的客户端 ip 和端口,并正常回 stun binding response。
  3. 记录客户端地址与用户的信息的映射关系。
  4. 服务器收到一个 rtp/rtcp 媒体数据包,通过包的源 ip 和端口,查询映射表就可以识别这个包属于哪个用户。
在分享完服务端端口选择的方案后,大家都知道 WebRTC 客户端使用 PeerConnection 来表示不同的媒体连接,这对于 WebRTC 来说是基础也是核心,在《聊聊 WebRTC 网关服务器》第二篇文章将继续为大家介绍如何选择 PeerConnection 的方案。

随着音频处理和压缩技术的不断发展,效果更好、适用范围更广、性能更高的算法和新的技术必将不断涌现,如果你有好的技术或者分享,欢迎关注网易 MC 官方博客以及微信公众号:**

关注更多技术干货内容:网易云信博客
欢迎关注网易云信 GitHub
欢迎关注网易云信官网

官网微信公众号:
聊聊 WebRTC 网关服务器1:如何选择服务端端口方案?

相关推荐