上篇文章,详细介绍了 WebRTC 技术。我们知道,WebRTC 标准中并没有规定信令服务器的实现,它把这部分的实现交给了程序开发者本身,一方面基于 WebRTC 的应用形态和技术栈可能是多种多样的,这样不但保持了技术中立性,还最大限度的确保了技术的灵活性和开放性;另外一方面,协议的设计是极其复杂的,要兼顾的场景很多,这样也保证了技术标准的简洁性。因此,只要符合 WebRTC 的通信流程和架构设计理念,信令服务器的实现方案应该是非常灵活的。

本文是此系列文章的第二篇,介绍 WebRTC 中信令服务器的设计。

信令介绍

在 WebRTC 的技术栈里,详细定义了一整套的规范,例如它的接口设计,使用 SDP 进行媒体协商、使用 ICE 收集网络地址并进行联通性检测等,这些规范使得客户端与客户端之间的数据交换变得非常容易和方便,但是我们发现 WebRTC 并没有对客户端建立点对点连接之前的过程定义规范,“空缺”的这部分,其实就是信令服务器在发挥作用的地方。

概括来说,WebRTC 信令是设备通信和交换点对点连接所需的信息的方式,包括交换应用程序之间的网络信息、协商媒体格式并处理通信会话的各个方面,因此在 WebRTC 的世界中,信令格外重要。

信令服务器作用

上面介绍了 WebRTC 中的信令,我们知道,WebRTC 的核心是点对点通信,在客户端连接建立之前,我们需要一个公共的服务器来实现上述信息的交换剂,这便是信令服务器,具体说来,一个信令服务器应该具备以下作用:

  • 交换通信双方的网络信息:
    • 最常见的是交换通信双方的 IP 和端口;
    • 两个 WebRTC 客户端之间会尽可能选择 P2P 进行通信。同一个局域网内,P2P 传输很容易实现;不同的局域网,需要借助网络穿透等技术手段实现 P2P 传输,若遇到网络穿透失败或者无法穿透的情况,则需要借助中转服务器实现数据传输。
  • 交换通信双方的媒体信息
    • 媒体信息用 SDP 表示,SDP 包含浏览器中的 RTP 媒体栈配置媒体会话所需要的全部信息,包括媒体类型(音频、视频、数据),所用的编解码器(Oplus、G.711 等)、用于编解码器的各个参数或设置、以及有关宽带的信息;
    • 信令通道也需要交换用于 SRTP 的密钥材料;
    • 总结一下,SDP 可以简单理解为:媒体类型的编码是什么、是否支持对应的媒体类型和编码器、编码方式是什么等。
  • 业务层的功能管理
    • 创建会话、加入已存在的会话、退出会话等;
    • 会话生命周期的管理和用户的管理等;
    • 客户端的身份认证。

因为我打算使用 WebRTC 技术实现一个文件传输的工具,因此本文更多讨论的是在文件传输工具的 WebRTC 实现下信令服务器的设计与实现。

WebRTC 信令工作流程

一个 WebRTC 系统信令的工作流程图大概如下:

  • 客户端 A 和客户端 B 通过 WebSocket 等协议请求信令服务器;
  • 客户端 A 与信令服务器之间的通信称为 offer-answer 机制,是 WebRTC 等一部分;
  • 客户端 A 和客户端 B 可以视为两个对等点,对等点之间的连接是为了在设备之间建立通信,在这之前对等点之间必须通过 WebRTC 信令服务器进行连接前的通信。

架构设计

介绍了信令服务器的作用后,我设计的文件传输工具信令服务器大体架构是这样:

架构整体结构不难,主要在于信令服务器对会话、用户等的管理,下面将详细说一下信令服务器这部分的管理功能。

管理模块

用户和房间管理

信令服务器能够对用户进行管理。两个需要建立点对点连接的用户,要能够找到彼此,需要借助房间的概念,即两个用户加入同一个房间,在同一个房间的用户可以交换彼此的连接信息,从而建立彼此的点对点连接。

在传输过程中,用户和房间的连接信息由信令服务器维护。再进一步扩展,信令服务器应当支撑多个 WebRTC 传输环境,即多个房间,且房间之间互不影响;每个房间参与的人数也应该不受限制,信令服务器应当支持多个用户可以进入同一个房间,可以选择对房间内特定的用户传输文件或者对房间内所有的用户传输文件。

会话管理

  • 信令服务器支持创建一个新的会话,允许客户端通过信令服务器交换剂网络信息和媒体信息;
  • 信令服务器还应当管理现有会话,允许新的用户加入现有的会话;
  • 不同的会话之前应该互不影响、相互隔离。

信令传输方式与协议

信令传输协议比较灵活,理论上可以选择多种通信协议。但是实际使用时,我们一般选择 TCP 或者基于 TCP 的 HTTP/HTTPS、WS/WSS 等应用层协议作为信令服务器的通信协议。

HTTP 传输

  • 浏览器可以发起新的 HTTP 请求,以便向服务器发送信令信息并从中接受信令消息;
  • 可以通过轮询或者 get 请求来从服务器获取信令信息

不难看出,通过 HTTP 协议的方式有非常明显的弊端,当房间新加入用户时,信令服务器没办法主动通知房间中已经存在的用户,即传统的 HTTP 协议没办法从服务端主动向客户端推送数据。

当然,这种弊端也是可以通过技术手段解决的,例如升级 HTTP2 或者客户端不断轮询请求信令服务器。

WebSocket 传输

  • WebSocket 允许浏览器开通一个与服务器的双向连接,客户端不仅能从信令服务器请求数据,信令服务器还能主动向客户端推送数据;
  • 现在主流的浏览器都支持 WebSocket,但某些 Web 代理和防火墙并不完全支持 WebSocket,可能会导致问题,尤其在身份验证方面。

NAT 穿透

本篇的最后来说一下客户端建立对等连接时的网络问题。

在一个 WebRTC 系统中,一个比较理想的情况是在客户端之间直接通过获取操作系统和网卡的 IP 地址建立点对点通信,我们一般称之为客户端之间处在同一个的内网中,但是实际中的场景往往复杂的多。目前我们日常使用的大部分设备都处在 NAT 设备后面,这就导致客户端没办法通过读取各自网卡的 IP 信息建立连接,在这种情况下,就需要借助 NAT 穿透技术。

关于 NAT 穿透技术,在本系列第一篇文章中已经提到可以借助 STUN/TURN 等方案实现 NAT 穿透,这里不再阐述,并且本篇文章主要关注 WebRTC 信令服务器的设计和实现,NAT 穿透技术的工作原理和工作流程将在本系列第三篇文章中详细展开说明。

这里先看一下 NAT 设备下信令服务器的通信过程:

  1. 前面已经说过,客户端通信前需要先建立对信令服务器的连接;
  2. NAT 设备的场景,交换剂信息前,客户端还需要与 STUN/TURN 建立连接,这样做的目的是通过 STUN/TURN 服务器获得各自的外网 IP 地址(子网和公网)、端口和 NAT 结构(IP 地址和端口对我们称之为 ICE Candidate)。连接后通信双方就可以通过信令服务器彼此交换信息了;
  3. 当获得彼此信息后,就可以尝试 NAT 穿透,客户端之间建立对等的 P2P 连接。

Reference

https://sheerbittech.medium.com/webrtc-signaling-server-everything-you-need-to-know-569f6b5c7317

https://juejin.cn/post/7171089420911640613