1. 引言
实时传输协议 (RTP) [1] 包含两个组成部分: 一个数据传输协议, 以及一个关联的控制协议 (RTCP). 传统上, RTP 和 RTCP 运行在不同的 UDP 端口上. 随着网络地址端口转换 (NAPT) [14] 的使用增加, 这种做法变得有问题, 因为维护多个 NAT 绑定可能代价较高. 它也会让防火墙管理更复杂, 因为必须打开多个端口才能允许 RTP 流量通过. 本备忘录讨论如何让单一媒体类型的 RTP 和 RTCP 流运行在一个端口上, 以简化 NAT 穿越和防火墙管理, 并考虑何时适合采用这种复用. 这里不讨论将多种媒体类型 (例如音频和视频) 复用到一个端口上 (但可参见 [1] 的 Section 5.2).
本备忘录的结构如下: Section 2 讨论导致使用独立端口的设计选择, 并说明这些选择对当前网络环境的适用性. Section 3 讨论术语, Section 4 讨论如何区分被复用的数据包. 随后, Section 5 规定 RTP 和 RTCP 应在何时以及如何复用, 以及如何对复用会话进行信令. Section 6 讨论服务质量和带宽问题. 最后, Section 7 给出安全考虑, Section 8 给出 IANA 考虑.
本备忘录更新 [1] 的 Section 11.
2. 背景
一个 RTP 会话包含数据包和周期性的控制 (RTCP) 数据包. RTCP 数据包假定使用 "与数据包相同的分发机制", 并且 "底层协议必须提供数据包和控制包的复用, 例如在 UDP 中使用不同的端口号" [1]. 复用被下放到底层传输协议, 而不是在 RTP 内部提供, 原因如下:
-
简单性: 将 RTP 和 RTCP 解复用移到传输层可以简化 RTP 实现, 因为实现无需关心数据包和控制包的分离. 这使实现能够以非常自然的方式组织, 并清晰分离数据平面和控制平面.
-
效率: 根据集成层处理 (integrated layer processing) 原则 [15], 当解复用发生在单一位置 (例如依据 UDP 端口) 时, 实现会比将解复用拆分到协议栈的多个层次 (例如先依据 UDP 端口, 再依据 packet type) 更高效.
-
支持第三方监测器: 虽然单播 IP 语音一直被纳入考虑, RTP 也被设计为支持松耦合的组播会议 [16] 和超大规模的组播流媒体应用程序 (例如所谓的三网融合 IP 电视 (IPTV) 服务). 因此, RTP 的设计允许 RTCP 数据包使用不同于数据包的独立 IP 组播组和 UDP 端口进行组播. 这不仅允许会话参与者获得接收质量反馈, 还支持部署第三方监测器, 使其能够在不访问数据包的情况下监听接收质量. 其目的是在不损害隐私的前提下, 为组播会话提供可管理性.
虽然这些设计选择适用于 RTP 的许多用途, 但在某些情况下会带来问题. 许多 RTP 部署并不使用 IP 组播, 并且随着网络地址转换 (NAT) 的使用增加, 在传输层进行复用的简单性已经变成一种负担, 因为它需要复杂的信令来打开多个 NAT 针孔. 在这类环境中, 更理想的做法是提供一种替代方案, 不再使用独立的 UDP 端口对 RTP 和 RTCP 进行解复用, 而是只使用一个 UDP 端口并在应用程序内部解复用.
本备忘录提供的正是这种替代方案: 在单一 UDP 端口上复用 RTP 和 RTCP 数据包, 并通过 RTP payload type 和 RTCP packet type 值进行区分. 这会给 RTP 实现增加一些额外工作, 换来更简单的 NAT 穿越.
3. 术语
本文档中的关键词 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", 和 "OPTIONAL" 应按 RFC 2119 [2] 中的说明解释.
4. 可区分的 RTP 和 RTCP 数据包
当 RTP 和 RTCP 数据包被复用到单一端口上时, RTCP packet type 字段在数据包中的位置与 RTP marker (M) bit 和 RTP payload type (PT) 的组合相同. 在满足两个限制时, 可使用该字段区分 RTP 和 RTCP 数据包: 1) 所使用的 RTP payload type 值不同于所使用的 RTCP packet type; 2) 对每个 RTP payload type (PT), PT+128 不同于所使用的 RTCP packet type. 第一个约束避免 RTP payload type 与 RTCP packet type 之间的直接冲突. 第二个约束避免设置了 marker bit 的 RTP 数据包与 RTCP 数据包之间发生冲突.
已知以下 RTP 与 RTCP packet type 之间的冲突:
-
RTP payload types 64-65 与原始 "RTP Payload Format for H.261 Video Streams" [3] 中定义的 (已废止) RTCP FIR 和 NACK 数据包冲突 (该文档已由 [17] 废止).
-
RTP payload types 72-76 与 RTP 规范 [1] 中定义的 RTCP SR, RR, SDES, BYE, 和 APP 数据包冲突.
-
RTP payload types 77-78 与 RTP/AVPF profile [4] 中定义的 RTCP RTPFB 和 PSFB 数据包冲突.
-
RTP payload type 79 与 RTCP 扩展报告 (Extended Report, XR) [5] 数据包冲突.
-
RTP payload type 80 与 "RTCP Extensions for Single-Source Multicast Sessions with Unicast Feedback" [6] 中定义的接收方摘要信息 (Receiver Summary Information, RSI) 数据包冲突.
未来可能会注册新的 RTCP packet type, 这会进一步减少在单一端口上复用 RTP 和 RTCP 时可用的 RTP payload type. 为支持这种复用, 未来的 RTCP packet type 分配应该在当前分配之后进行, 先使用 209-223 范围, 再使用 194-199 范围, 从而只阻塞 64-95 范围内的 RTP payload type. 只有在其他值已经耗尽时, 才应该使用 1-191 和 224-254 范围内的 RTCP packet type.
在这些约束下, 选择 RTP payload type 值时推荐遵循 RTP/AVP profile [7] 中的指南, 并增加一项限制: 64-95 范围内的 payload type 值不得使用. 具体而言, 在可能的情况下, 动态 RTP payload type 应该从 96-127 范围内选择. 如果该范围不足, 可以使用低于 64 的值. 在这种情况下, 推荐优先使用未由 [7] 静态分配的 payload type 编号.
注: 由于 [1] 的 Section 6.1 规定所有 RTCP 数据包必须作为复合数据包发送, 并以 Sender Report (SR) 或 Receiver Report (RR) 数据包开头, 读者可能会疑惑, 为什么在复用 RTP 和 RTCP 时还要禁止 72 和 73 以外的 RTP payload type. 这样做是为了支持 [18], 后者允许在某些情况下使用非复合 RTCP 数据包.