WebRTC 传输技术

作者:追风剑情 发布于:2024-2-29 14:56 分类:Unity3d

WebRTC基础传输技术架构.png

  这些技术不仅用于 WebRTC 底层,也广泛用于其他流媒体领域,比如 RTP/RTCP 广泛用于传统直播、监控等领域,理解这些技术的原理才能更好地使用 WebRTC 技术。

  在这些技术中,RTP/SRTP、SCTP 用于传输媒体流,提供拥塞和流控制功能;SDP、ICE、STUN、TURN 用于建立和维护网络连接,DTLS 则用于保护传输数据的安全。


RTP

  RTP (Real-time Transport Protocol,实时传输协议)通过 IP 网络实时传输音频和视频。 RTP 常用于流媒体服务的通信系统,例如网络电话、WebRTC 视频电话会议、电视服务等。 RTP 是由 Internet 工程任务组(IETF)的音视频传输工作组开发的,其标准规范 RFC 1889 于1996年发布,2003 年更新为 RFC 3550。

  RTP 是专为流媒体的端到端实时传输设计的,更关注信息的实时性,可以避免出现网络传输丢失数据造成通话质量下降的情况。例如,音频应用程序中丢失数据包可能会导致音频数据丢失几分之一秒,而使用合适的纠错算法就可以实现用户无感知。

  大多数 RTP 应用都是基于 UDP 构建的,并额外提供抖动补偿、包丢失检测和无序传递检测的功能。RTP 也支持 TCP,但是因为 TCP 更注重可靠性而不是实时性,所以在 RTP 应用中很少使用。

RTP 的主要特点如下。

  • 具有较低的延时。
  • 数据包在网络传输的过程中可能会丢失,到达对等端的顺序也可能发生变化。对等端收到 RTP数据包后,需要根据数据包的序列号和时间戳进行重新组合。
  • 支持多播(multicast),尽管目前 WebRTC还没有使用这个特性,但是在海量用户通话场景,这个特性就变得很重要。
  • 可用于音视频通话之外的场景,如实时数据流、状态实时更新、控制信息传输等连 续数据传输场景。

  尽管 RTP 的定位是低延时场景数据传输,但它本身并没有提供服务质量保障功能(Quality of Service,QoS),所以在 WebRTC 中,RTP 需要和 RTCP 结合使用。

  RTP 会为每个媒体流建立一个会话,即音频和视频流使用单独的 RTP 会话,这样接收端就能选择性地接收媒体流。RTP 使用的端口号为偶数,每个关联的 RTCP 端口为下一较高的奇数,端口号范围为 1024~65535。

RTP 配置文件与载荷

  RTP 在设计之初就考虑到了在不修改标准的情况下携带多种媒体格式并允许使用新格式,所以,RTP 标头数据中不包含媒体格式信息,而是在单独的 RTP 配置文件(profile)和有效载荷(payload)格式中提供,这种方式提供了更好的可扩展性。RTP 对每类应用(如音频或视频)都定义了一个配置文件和至少一个有效载荷格式。表 3-1 列出了几种特定应用的RTP 载荷。

特定应用的 RTP 载荷
载荷类型 名称 类型 通道数 频率(Hz) 默认包(ms) 参考规范
0 PCMU audio 1 8000 20 RFC 3551
8 PCMA audio 1 8000 20 RFC 3551
9 G722 audio 1 8000 20 RFC 3551
26 JPEG video
90000
RFC 3551
32 MPV video
90000
RFC 2250
34 H263 video
90000
RFC 3551
dynamic H264 AVC video
90000
RFC 6184
dynamic H264 SVC video
90000
RFC 6190
dynamic
H265 video
90000
RFC 7798
dynamic
opus audio 2 48000 20 RFC 7587
dynamic
mpeg4 audio/video
90000
RFC 3640
dynamic
VP8 video
90000
RFC 7741
dynamic
VP9 video
90000
draft-ietf-payload-vp9
dynamic jpeg2000 video
90000
RFC 5371

RFC3551.pdf

  载荷类型字段中定义了编解码的格式。每个配置文件都附带几种有效载荷格式规范,每个规范描述特定编码数据的传输。音频有效载荷格式包括 G.711、G.723、G.726、G.729、GSM、opus、MP3 和 DTMF 等,视频有效载荷格式包括 H.263 H.264、H.265 VP8 和 VP9 等。

RTP 配置文件包括以下 3 种。

  • 音频和视频会议的 RTP 配置文件(RFC 3551)。该配置文件定义了一组静态有效载荷类型分配以及使用会话描述协议(SDP)在有效载荷格式和 PT 值之间进行映射的动态机制。
  • SRTP(RFC 3711)定义了一个 RTP 配置文件,该配置文件提供用于传输有效载荷数据的加密服务,WebRTC 使用的就是 SRTP。
  • 用于机器对机器通信的 RTP (RTP/CDP) 实验性控制数据配置文件。

RTP 数据包标头

  在应用层创建 RTP 数据包并传递到传输层进行传输。应用层创建的 RTP 媒体数据的每个单元都以 RTP 数据包标头开始,标头结构如表 3-2 所示。

RTP 数据包标头域.png

  RTP 标头最小为 12 个字节。标头后面有可选的扩展头,随后是 RTP 有效载荷,其格式由特定应用类别确定。标头中各字段解释如下所示。

  • 版本号(2位): 表示协议的版本,当前版本是 2。
  • P(Padding,1位): 表示 RTP 数据包末尾是否有额外的 Padding 字节。Padding 字节用于填充一定大小的数据块,如加密算法,其最后一个字节表示 Padding 的字节 数(包括自身)。
  • X(扩展名,1位): 表示在标头和有效载荷数据之间是否存在扩展标头。
  • CC(CSRC 计数,4位): 表示包含 CSRC 标识符的数量。
  • M(标记,1位): 表示在应用程序级别使用的信令。对于视频,标记一帧的结束;对于音频,标记会话的开始。
  • PT(有效载荷类型,7位): 表示有效载荷的格式,从而确定应用程序对其的解释。值是特定于配置文件的,可以动态分配。
  • 序列号(16位): RTP 数据包的序列号。每发送一个 RTP 数据包,序列号都会递增,接收方将使用该序列号检测包丢失并适应无序交付。为了提升 RTP 的安全性,序列号的初始值应随机分配。
  • 时间戳(32位): RTP 数据包的时间标识。接收端以此在适当的时间播放接收到的样本。当存在几个媒体流时,每个流的时间戳都是独立的。时序的粒度特定于应用程序,如音频应用程序的常见采样率是每 125μs 对数据进行一次采样,换算成时钟频率为 8kHz,而视频应用程序通常使用 90kHz 时钟频率。时间戳反映了发送者采样 RTP 报文的时刻,接收者使用时间戳计算延迟和延迟抖动,并进行同步控制。
  • SSRC(32位): 表示 RTP 数据包的同步源,用于标识媒体源。同一 RTP 会话中的同步源是唯一的。
  • CSRC(32位): 表示 RTP 数据包的贡献源,同一 RTP 会话可以包含多个贡献源。
  • 标头扩展名: 可选项,由扩展名字段决定是否存在。第一个 32 位字包含一个特定于配置文件的标识符(16位)和一个长度说明符(16位)。

RTCP

  RTCP(RTPControlProtocol) 是实时传输协议(RTP)的姊妹协议,其基本功能和数包结构在 RFC 3550 中定义。RTCP 为 RTP 会话提供带外统计信息和控制信息,与 RTP 协作提供多媒体数据的传输和打包功能,其本身不传输任何媒体数据。

  RTCP 的主要功能是定期发送数据包计数、数据包丢失、数据包延迟变化以及往返延迟时间等统计信息,向媒体参与者提供媒体分发中的服务质量保障。应用程序在接收到这些信息后,可以通过限制流量或更换编解码格式的方式提升服务质量。RTCP 流量的带宽很小,通常约为总占用带宽的5%。

  RTP 通常在偶数 UDP 端口上发送,而 RTCP 消息将在下一个更高的奇数端口发送。

  RTCP 本身不提供任何流加密或身份验证方法。如果对安全性有更高的要求,可以使用 RFC 3711 中定义的 SRTP 实现此类机制,WebRTC 便采用了SRTP。

RTCP 提供以下功能。

  • 在会话期间收集媒体分发质量方面的统计信息,并将这些数据传输给会话媒体源和其他会话参与方。源可以将此类信息用于自适应媒体编码(编解码器)和传输故障检测。如果会话是多播网络承载的,则允许进行非侵入式会话质量监视。
  • RTCP 为所有会话参与者提供规范的端点标识符(CNAME)。 CNAME 是跨应用程序示例端点的唯一标识。尽管 RTP 流的 SSRC也是唯一的,但在会话期间,SSRC与端点的绑定关系仍可能改变。
  • 提供会话控制功能。RTCP 是联系所有会话参与者的便捷方式。

  在数以万计的接收者参与的直播会话中,所有参与者都发送 RTCP 报告,网络流量与参与者的数量成正比。为了避免网络拥塞,RTCP 必须支持会话带宽管理功能。RTCP 通过动态报告传输的频率来实现这一功能;RTCP 带宽使用率通常不应超过会话总带宽的 5%,应始终将 RTCP 带宽的 25% 预留给媒体源,以便在大型会议中,新的参与者可以接收发送 者的 CNAME 标识符而不会产生过多延迟。

  RTCP 报告间隔是随机的,最小报告间隔为5秒,通常发送 RTCP 报告的频率不应低于5秒一次。

RTCP数据包标头.png

RTCP 标头长度为 4 个字节,标头中各字段解释如下。

  • 版本号(2位): 表示 RTCP 的版本号。
  • P(1位): 表示 RTP 数据包末尾是否有额外的 Padding 字节。Padding 字节用于填充一定大小的块,最后一个字节表示 Padding 的字节数(包括自身)。
  • RC(5位): 表示此数据包中接收报告块的数量,可以为 0。
  • PT(8位): 包含一个常数,用于表示 RTCP 数据包类型。
  • 长度(16位): 表示此 RTCP 数据包的长度。
  • SSRC(32位): 同步源标识符,用于唯一标识媒体源。

RTCP 支持以下几种类型的数据包。

1.发送者报告(SR)
  活跃发送者在会议中定期发送报告,报告该时间间隔内发送的所有 RTP 数据包的发送和接收统计信息。发送者报告包含绝对时间戳,表示自1900年1月1日零点以来经过的秒数。绝对时间戳帮助接收方同步 RTP 消息,对于同时传输音频和视频的场景尤为重要,因为音频和视频的 RTP 流独立使用相对时间戳,必须使用 RTCP 绝对时间戳进行同步。

2.接收者报告(RR)
  接收者报告适用于不发送 RTP 数据包的被动参与者,用于通知发送者和其他接收者服务质量。

3.源描述(SDES)
  源描述可以用于将 CNAME 项发送给会话参与者,也可以用于提供其他信息,例如名称、电子邮件地址、电话号码以及源所有者或控制者的地址。

4.关闭流(BYE)
  源发送 BYE 消息以关闭流,允许端点 (endpoint) 宣布即将离开会议。

5.特定于应用程序的消息(APP)
  APP 提供了一种机制,用于扩展 RTCP。

SRTP/SRTCP

  对于未加密的实时通信应用,可能会遇到多种形式的安全风险。在浏览器和浏览器之间,或者浏览器和服务器通信之间传输未加密的数据时,都有可能被第三方拦截并窃取。

  基础的 RTP 没有内置任何安全机制,因此不能保证传输数据的安全性,只能依靠外部机制进行加密。实际上,WebRTC规范明确禁止使用未加密的 RTP。出于增强安全性的考虑,WebRTC 使用的是 SRTP。

  SRTP是RTP的一个配置文件,旨在为单播和多播应用程序中的 RTP 数据提供加密消息身份验证和完整性以及重放攻击保护等安全功能。SRTP 有一个姊妹协议:安全RTCP(SRTCP),它提供了与 RTCP 相同的功能,并增强了安全性。

  使用SRTP或SRTCP时必须启用消息身份验证功能,其他功能(如加密和身份验证)则都是可选的。

  SRTP 和 SRTCP 默认的加密算法是 AES,攻击者虽然无法解密数据,但可以伪造或重放以前发送的数据。因此,SRTP 标准还提供了确保数据完整性和安全性的方法。

  为了验证消息并保护其完整性,SRTP 使用HMAC-SHA1算法计算数据内容的摘要,并将摘要数据附加到每个数据包的身份验证标签。接收者收到数据后也同样计算摘要数据,如果摘要数据相同,表示内容完整;如果摘要数据不同,表示内容不完整或者被篡改了。

注意   SRTP仅加密RTP数据包的有效载荷,不对标头进行加密。但是,标头可能包含需要保密的各种信息。RTP 标头中包含的此类信息之一就是媒体数据的音频级别。实际上,任何看到 SRTP 数据包的人都可以判断出用户是否在讲话。尽管媒体数据是加密的,但这仍有可能泄露重要的隐私。

TLS/DTLS

  安全套接层( Secure Socket Layer,SSL)是为网络通信提供安全保证及数据完整性的一种安全协议。SSL 由网景公司 (Netscape) 研发,用于确保互联网连接安全,保护两个系统之间发送的敏感数据,防止网络犯罪分子读取和篡改传输信息。IETF 对 SSL 3.0 进行了标准化,并添加了一些机制,经过标准化的 SSL 更名为 TLS(Transport Layer Security,安全传输层)协议。所以,可以将 TLS 理解为 SSL 标准化后的产物,SSL 3.0 对应着 TLS 1.0版本。

  TLS的最新版本是 1.3,在 RFC 8446 中定义,于2018年8月发布。

  由于TLS是基于TCP,不能保证UDP上传输的数据的安全性,因此在 TLS 协议架构上进行了扩展,提出 DTLS(Datagram Transport Layer Security,数据包传输层安全性)协议,使之支持UDP,DTLS 即成为 TLS 的一个支持数据包传输的版本。DTLS 使用非对称加密方法,对数据身份验证和消息身份验证提供完全加密。

  在 WebRTC 规范中,加密是强制要求的,并在包括信令机制在内的所有组件上强制执行。其结果是,通过 WebRTC 发送的所有媒体流都通过标准化的加密协议进行安全加密在选择加密协议时,具体取决于通道类型;通过 RTCDataChannel发送的数据流使用 DTLS 协议加密;通过 RTP 传输的音视频媒体流则使用 SRTP 加密。

  DTLS 协议内置在 WebRTC 的标准化协议中,并且是在 Web 浏览器、电子邮件和 VoIP平台中始终使用的协议,这意味着基于Web的应用程序无须提前设置。

SDP

SDP(Session Description Protocol)是用于描述媒体信息的协议,以文本格式描述终端功能和首选项。SDP 只包含终端的媒体元数据,不包含媒体数据内容。建立连接的双方通过交换SDP获取彼此的分辨率、编码格式、加密算法等媒体信息。SDP 广泛用于会话启动协议(SIP)、RTP 和实时流协议 (RSP)

SDP通常包含如下内容。

  • 会话属性。
  • 会话活动的时间。
  • 会话包含的媒体信息。
  • 媒体编/解码器。
  • 媒体地址和端口信息。
  • 网络带宽的信息。

  WebRTC使用SDP交换双方的网络和媒体元数据,当遇到连接失败、黑流等问题时分析 SDP 往往是查找问题最为有效的方法。

SDP字段含义及格式
字段 含义 格式
v= SDP版本 v=0
o= 会话发起人和标识信息 o=<username> <session id> <version> <network type> <address type> <address>
s= 会话名称 s=<session name>
i=* 会话信息 i=<session description>
u=* 描述的URI u=<URI>
e=* email地址 e=<email address>
p=* 电话号码 p=<phone number>
c=* 连接信息 c=<network type> <address type> <connection address>
b=* 带宽信息 b=<modifier><bandwidth-value>
z=* 时区校正 z=<adjustment time> <offset>
k=* 密钥 k=<method>:<encryption key>
a=* 会话属性 a=<attribute>:<value>
t= 会话有效时间 t=<start time> <stop time>
r=* 重复次数 r=<repeat interval> <active duration> <list of offsets from start-time>
m= 媒体名称和传输地址 m=<media> <port> <transport> <fmt list>
i= 标题 i=<media or session title>

a=sendonly: 仅发送
a=recvonly: 仅接收
a=sendrecv: 发送且接收 (默认)
a=inactive: 不发送且不接收
m=video 0: 将视频流端口号设为0,将告诉对方不要向我发送视频流
m=audio 0: 将音频流端口号设为0,将告诉对方不要向我发送音频流

RTCRtpTransceiverDirection 枚举值说明
枚举值 RTCRtpSender RTCRtpReceiver
sendrecv 可发送RTP数据 可接收RTP数据
sendonly 可发送RTP数据 不可接收RTP数据
recvonly 不可发送RTP数据 可接收RTP数据
inactive 不可发送RTP数据 不可接收RTP数据
stopped 已停止状态,不可发送RTP数据 已停止状态,不可接收RTP数据

profile-level-id 在 RFC6184.pdf 中的 8.1 Media Type Registration 一节中有比较详细的说明。

示例: SDP

v=0
o=- 9091110935569930485 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video
a=msid-semantic: WMS
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 102 0 8 106 105 13 110 112 113 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:cgZt
a=ice-pwd:PSTgUM5/bO/YbTCEf+BzW3PF
a=ice-options:trickle
a=fingerprint:sha-256 75:23:AB:9C:C3:85:35:A1:D7:D6:E8:B8:C8:74:F0:17:FB:94:B9:33:F5:C2:99:E6:4B:0F:1B:59:4B:77:E9:6B
a=setup:active
a=mid:audio
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=sendrecv
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:102 ILBC/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:112 telephone-event/32000
a=rtpmap:113 telephone-event/16000
a=rtpmap:126 telephone-event/8000
a=ssrc:3438513994 cname:2AX17pxsyuP+nHGy
a=ssrc:3438513994 msid: ef806185-998d-47f6-9410-f30d2343ad60
a=ssrc:3438513994 mslabel:
a=ssrc:3438513994 label:ef806185-998d-47f6-9410-f30d2343ad60
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 127 123 125
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:cgZt
a=ice-pwd:PSTgUM5/bO/YbTCEf+BzW3PF
a=ice-options:trickle
a=fingerprint:sha-256 75:23:AB:9C:C3:85:35:A1:D7:D6:E8:B8:C8:74:F0:17:FB:94:B9:33:F5:C2:99:E6:4B:0F:1B:59:4B:77:E9:6B
a=setup:active
a=mid:video
a=extmap:14 urn:ietf:params:rtp-hdrext:toffset
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:13 urn:3gpp:video-orientation
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
a=sendrecv
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:96 VP8/90000
a=rtcp-fb:96 goog-remb
a=rtcp-fb:96 transport-cc
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=96
a=rtpmap:98 VP9/90000
a=rtcp-fb:98 goog-remb
a=rtcp-fb:98 transport-cc
a=rtcp-fb:98 ccm fir
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=fmtp:98 x-google-profile-id=0
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=98
a=rtpmap:127 red/90000
a=rtpmap:123 rtx/90000
a=fmtp:123 apt=127
a=rtpmap:125 ulpfec/90000
a=ssrc-group:FID 2622658340 3231838899
a=ssrc:2622658340 cname:2AX17pxsyuP+nHGy
a=ssrc:2622658340 msid: 43924dce-65e8-499d-a4f6-081b62c3bd2b
a=ssrc:2622658340 mslabel:
a=ssrc:2622658340 label:43924dce-65e8-499d-a4f6-081b62c3bd2b
a=ssrc:3231838899 cname:2AX17pxsyuP+nHGy
a=ssrc:3231838899 msid: 43924dce-65e8-499d-a4f6-081b62c3bd2b
a=ssrc:3231838899 mslabel:
a=ssrc:3231838899 label:43924dce-65e8-499d-a4f6-081b62c3bd2b  

ICE

  ICE (Interactive Connectivity Establishment,交互式连接建立协议)是用于提案/应答模式的 NAT(网络地址转换)传输协议,主要用于在 UDP 协议下建立多媒体会话。对于采用 Mesh 结构的 WebRTC应用程序,当通信双方尝试建立 P2P 连接时,如果有一方(或者双方)位于 NAT 网络内部,则直接建立 P2P 连接会失败,这时候必须有一种能够突破 NAT 限制的技术,这个技术就是 ICE 协议。

  由于 IPv4 地址资源较为有限,而且目前仍然在大量使用,因此大多数接入互联网的设备都部署于 NAT 网络内部,不是真正拥有一个公网IPv4 地址。NAT 网关将出站请求地址动态映射为公网地址,相应地,将入站请求转换为内网地址,以确保内部网络上的路由正确。由于NAT 的限制,在使用内网 IP 地址建立 P2P 连接时经常会出现连接失败的情况 ICE 技术可以克服 NAT 的限制,是建立 P2P 网络连接的最佳路径。

  尝试建立连接的双方都有可能位于 NAT 网络之中,也就是说它们都不能直接使用IP地址建立网络连接。

  使用 ICE 技术建立网络连接的步骤如下所示。

  第一次尝试: ICE 首先尝试使用本地网卡地址与对等方建立 P2P 连接,此地址通常为内网地址。如果连接双方位于同一个内网,则成功建立连接。

  第二次尝试: 如果第一次尝试失败(这对于双方都位于 NAT 网络内部的情况是不可免的,由于网络的复杂性,也可能会由其他原因导致连接失败),则ICE将使用STUN服务器获取 NAT 设备的公网 IP 地址及映射端口,并尝试使用该 IP 地址建立连接。对于只有一方位于 NAT 网络内部,或者双方都位于非对称 NAT 网络内的情况,连接通常会成功建立。

  第三次尝试: 如果第二次尝试失败,意味着双方无法直接建立 P2P 连接,这时需要通过一个中介进行数据中转,这个中介即 TURN 服务器。也就是说,第三次尝试是直接与 TURN 服务器建立连接,而随后的媒体数据流将通过 TURN 中继服务器进行转发。

  TURN 服务器通常会架设在数据中心,并指定公网 IP 地址,只要 TURN 服务器正常则在网络通畅的情况下,通信双方与 TURN 服务器建立连接一定会成功。

  在上述情况中,ICE 尝试建立连接所使用的地址称为候选地址,这是因为这些地址能否成功建立连接是不确定的,需要尝试后才能确定。候选地址以文本的格式呈现,多个候选地址按如下顺序排序。

  • 使用内网IP地址。
  • 使用 STUN 发现公网 IP 地址。
  • 使用 TURN 作为网络中继。

ICE 是在所有的候选地址中,选择开销最小的路由。

RTCIceCandidateType 枚举值说明
候选者种类 说明
host 本机候选者
srflx 映射候选者
prflx 来自对称NAT的映射候选者
relay 中继候选者

示例: ICE Candidate

sdpMid=audio
sdpMLineIndex=0
sdp=candidate:1974571332 1 udp 2122260223 192.168.0.115 55765 typ host generation 0 ufrag cgZt network-id 1  

1. NAT

  NAT 是一种实现内网主机与互联网通信的方法。使用这种方法时需要在内网出口设备上安装 NAT 软件,而这种装有 NAT 软件的设备叫作 NAT 路由器,且需要至少有一个有效的公网 IP 地址。这样,所有使用内网地址的主机在和外界通信时,都要在 NAT 路由器上将内网地址转换成公网 IP 地址,才能和互联网连接。NAT 将自动修改 IP 报文的源 IP 地址和目的 IP 地址,IP 地址校验则在 NAT 处理过程中自动完成。

  NAT 的应用极为广泛,当我们接入某个局域网,或者连接 Wi-Fi 时,我们实际上已经处于 NAT 网络之中了。NAT 具有以下优点。

  • 共享上网: NAT 技术通过地址和端口映射,使用少量公网 IP 即可实现大量内网IP地址共享上网。
  • 提高网络安全性: 不同的内网 IP 地址映射到少量公网 IP 地址,对外隐藏了内网网络结构,从而防止外部攻击内网服务器,降低了网络风险。
  • 方便网络管理: 通过改变映射关系即可实现内网服务器的迁移和变更,便于对网络进行管理。
  • 节省成本: 使用了少量公网 IP 地址,节省了 IP 地址的注册及使用费用。

按照地址转换方法进行划分,NAT 分为如下4类。

(1)全锥形 NAT (Full cone NAT)

  一旦一个内网地址 (ip1:port1) 映射到公网地址 (ip2:port2),所有发自 ip1:port1 的包都经由 ip2:port2 向外发送。任意外部主机都能通过向 ip2:port2 发包到达 ip1:port1。

(2)地址受限锥形 NAT (Address-Restricted cone NAT)

  只接收曾经发送到对端 IP 地址的数据包。一旦有一个内网地址 (ip1:port1) 映射到公网地址 (ip2:port2 ),所有发自 ip1:port1 的包都经由 ip2:port2 向外发送。任意外部主机(hostAddr:any)都能通过向 ip2:port2 发包到达 ip1:port1,但前提是 ip1:port1 之前有向 hostAddr:any 发送过包,any 表示端口不受限制。

(3)端口受限锥形 NAT (Port-Restricted cone NAT)

  类似地址受限锥形 NAT,但是端口也受限制。一旦有一个内网地址 (ip1:port1) 映射到外网地址 (ip2:port2 ),所有发自 ip1:port1 的包都经由 ip2:port2 向外发送。一个外部主机(hostAddr:port3)能够发包到达 ip1:port1 的前提是 ip1:port1 之前有向 hostAddr:port3 发送过包。

(4)对称NAT(Symmetric NAT)

  映射的外网地址端口号不固定,会随着目的地址的变化而变化。

  锥形 NAT 与对称 NAT 的区别在于,在 NAT 已分配端口号 port2 给客户端的情况下如果 Client 继续用 port1 端口与另一外网服务器通信,锥型 NAT 还会继续用原来的 port2 端口,即所分配的端口号不变。而对于对称 NAT,NAT 将会分配另一端口号 (如 port3) 给 Client 的 port1 端口。也就是说,同一内网主机、同一端口号,对于锥形 NAT,无论与哪一个外网主机通信,都不改变所分配的端口号; 而对于对称 NAT,同一内网主机、同一端口 号,每一次与不同的外网主机通信,就重新分配一个端口号。

  对称 NAT 的这个特性使得位于该网络下的 WebRTC 用户无法使用 STUN 协议建立 P2P 连接。

2. STUN与TURN

  位于 NAT 网络内的设备能够访问互联网,但并不知道 NAT 网络的公网 IP 地址,这时候就需要通过 STUN 协议实时发现公网 IP。

  STUN (Session Traversal Utilities for NAT)是一种公网地址及端口的发现协议,客户端向 STUN 服务发送请求,STUN 服务返回客户端的公网地址及 NAT 网络信息。

  对于建立连接的双方都位于对称 NAT 网络的情况,使用 STUN 发现网络地址后,仍然无法成功建立连接。这种情况就需要借助 TURN 协议提供的服务进行流量中转。

  TURN(Traversal Using Relays around NAT)通过数据转发的方式穿透NAT,解决了防火墙和对称NAT的问题。TURN 支持UDP和TCP 协议。

  通信双方借助STUN协议能够在不使用TURN的情况下成功建立P2P连接。如有特殊情况,无法建立P2P 连接,则仍需要使用TURN进行数据转发。

注意   使用 STUN 建立的是 P2P 的网络模型,网络连接直接建立在通信两端,没有中间服务器介入;而使用 TURN 建立的是流量中继的网络模型,用户两端都与 TURN 服务建立连接,用户的网络数据包通过 TURN 服务进行转发。

3.ICE 候选者

  ICE候选者描述了用于建立网络连接的网络信息,包含网络协议、IP地址、端口等如果设备上有多个IP地址,那么每个IP地址都会对应一个候选。例如设备A上有内网IP地址IP-1,还有公网IP地址IP-2,A通过IP-1可以直接与B进行通信,但是WebRTC不会判断优先使用哪个IP地址,而是同样从两个IP地址收集候选,并将候选放在SDP中作为提案发送给 B。

  设备A和B很有可能位于NAT网络环境中,这时就涉及另外两种类型的候选: NAT映射候选和TURN中继候选。当使用TURN服务时,两种类型的候选都从TURN获取;如果只使用了 STUN 服务,则只需要获取NAT映射候选。

图3-3使用了TURN服务来发现这两种类型的候选,X:x指的是IP地址X和UDP端口x。

ICE候选者发现步骤.png

  在图3-3中,设备A向TURN服务发起了地址分配请求,由于A位于NAT网络环境下,NAT将创建一个映射地址X1:x1,为设备A收发网络数据包,如果A位于多个NAT设备下,那么每个NAT都会创建一个映射地址,但是只有最外层的映射地址能够被TURN服务发现。

  TURN服务收到请求后,会在自己的地址Y上分配一个端口y,将Y:y作为中继候选发送给设备A。设备A完成3种类型候选的收集后,将它们按照优先级从高到低排序,以会话属性的形式加入SDP,然后通过信令服务器发送给设备B。设备B收到设备A的候选信息后,也以同样的方式完成自己的候选信息收集,并回传给设备A。这时候A和B都有了自己和对方的候选信息,WebRTC会将这些候选信息进行配对,再进行连通性检查,使用通过检查的候选对建立网络连接。

4.ICE候选者在SDP中的语法

ICE候选者在SDP中的语法格式如下的代码清单所示。

a=candidate:<foundation> <component-id> <transport> <priority> <connection-address> <port> <cand-type>
//举例
a=candidate:4234997325 1 udp 2043278322 192.168.0.56 44323 host  

代码清单中的字段说明如下:

foundation:创建标识。
component-id:值为1表示RTP协议,值为2表示RTCP协议。
transport:传输协议,可以使用UDP和TCP,由于UDP性能好,故障恢复快,推荐使用UDP。
priority:优先级,综合考虑延时、带宽开销、丢包等因素,候选类型的优先级一般是 host>srvflx>prflx>relay。
connection-address:IP地址。
port:端口。
cand-type:候选类型,UDP候选类型取值有 host(本机候选)、srflx(映射候选)、relay(中继候选)和prflx(来自对称NAT的映射候选)。

5.ICE配对

将本地ICE候选项和对等端ICE候选项进行一一对应,每一组称为一个ICE候选对。

在进行ICE建连协商时,ICE层将从两端选择一个作为控制代理(controlling agent),另外一端作为受控代理(controlled agent)。

控制代理负责决定建立连接使用的ICE候选对,并将最终结果发送给受控代理,受控代理只需要等待结果。

控制代理通常会为同一个ICE会话选择多个候选对,每选择一个候选对都会通知受控 代理,两端同时使用新的候选对尝试建立连接。

当控制代理发送完所有的候选项时,需要通知对等端,做法是将RTCIceCandidatecandidate 属性设置为空字符串,调用addIceCandidate()方法将RTCIceCandidate加入ICE连接。

当ICE协商完成后,当前正在使用的候选对即为最终配对结果。如果出现ICE重新协商,则重新开始配对。需要注意的是,由于网络连接配置可能发生变化(如切换网络),每次最终配对的结果可能不同。

RTCIceCandidate.transport.role属性指出了当前ICE的代理角色,代理角色的控制由WebRTC自动完成,通常不需要我们关注它。

6.ICE重启

  使用WebRTC的应用程序时,网络环境经常会发生变化,比如用户可能从Wi-Fi切换到移动网络,或者从移动网络切换到Wi-Fi,网络故障导致的闪断现象也时有发生。

  当出现网络切换或者网络中断的情况时,需要重新协商网络连接,协商过程与最初建立连接相同,这个过程称为ICE重启。ICE重启能够确保媒体流的传输不会中断,实现平滑的网络切换。

7.ICE Trickle

  在实际使用过程中,ICE技术存在的一个问题是呼叫建连很慢,原因是ICE协商过程耗费了过多时间。客户端在发起呼叫时先与STUN服务器通信,从STUN服务器获取映射候选地址和中继候选地址,加上本地候选地址,构造三类ICE候选。之后把这三类候选放到SDP属性中(a=*),完成这个动作后才实际发起SDP提案(offer)请求。接收者经过同样的过程,待两边都收到对方完整的SDP信息后才开始进行实际的P2P建连。建连要发生在所有候选都获取完后,造成大量时间浪费,所以为了加快通话建立的速度,建议把连通性检测提前,即ICETrickle方案。该方案的思想是客户端一边收集候选一边发送给对方比如本地候选不需要通过STUN服务获取,直接就可以发起,这样节省了连通性检测的时间。

  在 WebRTC 中使用 ICE Trickle,需要在对象 RTCPeerConnection 监听事件 icecandidate。WebRTC完成本地ICE候选者的搜集后,会触发该事件,该事件对象中包含candidate属性,然后使用信令服务器将candidate传送给对等端。

//WebRTC使用ICE Trickle
//在RTCPeerConnection对象中监听icecandidate
peerConnection.addEventListener('icecandidate', event => {
	if (event.candidate) {
		signalingChannel.send({'new-ice-candidate': event.candidate});
	}
});
//在信令服务器上监听对等端的ICE信息,并将ICE信息加入本地RTCPeerConnection
siqnalingChannel.addEventListener('message', async message => {
	if (message.iceCandidate) {
		try {
			await peerConnection.addIceCandidate(message.iceCandidate);
		} catch (e) {
			console.error('Error adding received ice candidate', e);
		}
	}
});

标签: Unity3d

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号