ICE策略

在 WebRTC 中,ICE 的连接策略是可定制的。在 5.7.1 节中介绍 RTCPeerConnection 对象时,我们曾讲过可以给它传入一个 JSON 格式的参数但当时并没有对传入的参数做详细的介绍。现在我们来介绍该参数。

构造 RTCPeerConnection 对象时,其输入参数的类型为 RTCConfiguration。RTCConfiguration 在 WebRTC 规范中的定义参见代码 6.1。

代码6.1 RTCConfiguration 结构体
dictionary RTCConfiguration {
  sequence<RTCIceServer> iceServers;
  RTCIceTransportPolicy iceTransportPolicy;
  RTCBundlePolicy bundlePolicy;
  RTCRtcpMuxPolicy rtcpMuxPolicy;
  sequence<RTCCertificate> certificates;
  [EnforceRange] octet iceCandidatePoolSize = 0;
};

下面详细解释一下 RTCConfiguration 结构中各字段的含义,如表 6.1 所示。

image 2025 02 23 11 28 30 400
Figure 1. 表6.1 RTCConfiguration 各字段含义

通过表 6.1,我们已经对 RTCConfiguration 中各字段的含义了解得非常清楚了。不过,其中的 iceServers 字段还需要再解释一下。iceServers 是 RTCIceServer 类型的数组,RTCIceServer 结构定义参见代码 6.2。

代码6.2 RTCIceServer结构体
dictionary RTCIceServer {
  required (DOMString or sequence<DOMString>) urls;
  DOMString username;
  DOMString credential;
  RTCIceCredentialType credentialType = "password";
};

该结构中各字段的含义如下:url,指明了服务的地址;username 和 credential,指明了访问 url 地址时使用的用户名和密码;credentialType,指明授权方式为密码方式,也是目前唯一的授权方式。

了解了上面这些内容后,再来看一下具体的例子,看看在真实场景中是如何使用 RTCConfiguration 的,具体如代码 6.3 所示。

代码6.3 PeerConnection配置
var pcConfig = {
  iceServers: [
    {
      urls: 'turn:stun.learningrtc.cn:3478',
      username: 'username1',
      credential: 'password1'
    },
    {
      urls: 'turn:stun.avdancedu.com:3478',
      username: 'username2',
      credential: 'password2'
    }
  ],
  iceTransportPolicy: 'all',
  bundlePolicy: 'max-bundle',
  rtcpMuxPolicy: 'require'
};

let pc = new RTCPeerConnection(pcConfig);

// ...

在上面的 RTCConfiguration 对象中,包含了两个 TURN 服务器,分别是 stun.learningrtc.cn 和 stun.avdancedu.com,相当于为 WebRTC 增加了两个 relay 类型的 Candidate。当内网和 P2P 无法连通时,RTCPeerConnection 会尝试与这两台中继服务器连接,如果其中一台连接成功,就不再尝试连接另一台。

示例中,除了设置多个 TURN 服务器外,在 RTCConfiguration 中还将 iceTransportPolicy 字段设置为 all,表示按 Candidate 优先级次序尝试连接;bundlePolicy 设置为 max-bundle,表示让所有媒体数据使用同一个 Candidate,这样更有利于端口资源的利用;rtcpMuxPolicy 设置为 require,表示 RTCP 与 RTP 数据共用同一个 Candidate。