1.1 发展史、标准协议族与核心术语 本节是全书的第一块地砖:后续所有章节的类名、报文名、指标名,都能在本节的协议族分层与术语表里找到出处。先建坐标,再进机房。 从话音引擎到事实标准 WebRTC 不是从零设计的。它的核心技术底座来自一家瑞典公司 GIPS 的语音与视频引擎,这家公司靠回声消除和抗丢包技术在 VoIP 时代名声很响。2011 年 Google 收购 GIPS 并把引擎开源,同年与 Mozilla 联合宣布在浏览器里开放实时通信能力。这件事的行业意义在于:此前做一个视频通话应用,音频引擎、编解码、抗弱网这些最难的部件全要自研或买授权,小团队根本碰不动;开源之后,这些部件被装进了每台浏览器,调用几个标准接口就能用。 标准化走了两条线。
本节是全书的第一块地砖:后续所有章节的类名、报文名、指标名,都能在本节的协议族分层与术语表里找到出处。先建坐标,再进机房。
WebRTC 不是从零设计的。它的核心技术底座来自一家瑞典公司 GIPS 的语音与视频引擎,这家公司靠回声消除和抗丢包技术在 VoIP 时代名声很响。2011 年 Google 收购 GIPS 并把引擎开源,同年与 Mozilla 联合宣布在浏览器里开放实时通信能力。这件事的行业意义在于:此前做一个视频通话应用,音频引擎、编解码、抗弱网这些最难的部件全要自研或买授权,小团队根本碰不动;开源之后,这些部件被装进了每台浏览器,调用几个标准接口就能用。
标准化走了两条线。W3C 负责 API 面,定义浏览器暴露给 JavaScript 的对象和行为;IETF 负责协议面,把线上跑的报文格式与流程定成 RFC。两条线在 2021 年前后才双双落定为正式推荐标准,可见其间博弈之复杂。对读源码的人,这段历史有个直接后果:libwebrtc 是先有实现后有标准,标准又反过来改造实现,所以代码里同时存在旧模型的残留与新模型的接管,命名风格也不统一。看到设计"奇怪"的地方,先想到历史沉积,再想到设计意图,这是读这套代码的基本修养。
WebRTC 在 IETF 侧是一族协议的集合,按职责可以排成五层。这张表值得背下来,后面遇到任何报文或类名,先问它属于哪一层。
| 层次 | 协议与 RFC | 职责 | 典型报文或产物 |
|---|---|---|---|
| 信令 | SDP 与 JSEP 相关文档 | 交换会话描述,协商媒体参数 | offer 与 answer 文本 |
| 穿越与传输 | ICE、STUN、TURN | 找到可通线路并维持 | STUN 绑定请求与响应 |
| 媒体传输 | RTP、RTCP | 打包媒体流,反馈质量 | RTP 数据包、SR 与 RR 报告 |
| 安全 | DTLS、SRTP | 握手导出密钥,加密媒体 | DTLS 握手包、加密后的 RTP |
| 数据通道 | SCTP over DTLS | 可靠或不可靠的双向数据 | DATA_CHANNEL 打开消息 |
两点容易被误解的地方要挑明。其一,信令层是刻意不标准化的:会话描述文本用什么通道送、格式怎么包装,规范只要求应用自定,所以市面上信令有走 WebSocket 的、有走 HTTP 轮询的,libwebrtc 本身根本不含信令服务器代码——引擎只负责生成与消费 SDP 文本,运输完全交给应用层。其二,安全层的密钥不经过信令:DTLS 握手直接发生在两个媒体终端之间,SDP 里交换的只是证书指纹,用来核对握手对端没有被人调包。这个设计让中间的信令服务器纵然被攻破,也拿不到解密媒体的能力。
libwebrtc 的类名几乎都能在这些术语里找到对应。理解了术语,等于拿到了命名规则表。
| 术语 | 含义 | 对应源码概念 |
|---|---|---|
| PeerConnection | 一条端到端连接的总管 | pc 层的同名接口与实现 |
| Track | 一条媒体轨道,音或视频 | MediaStreamTrack 及其音视频子类 |
| Source 与 Sink | 轨道的源头与出口 | 生产者消费者接口对 |
| RtpSender 与 RtpReceiver | 轨道的发送与接收句柄 | 负责编码封装与解包分发 |
| RtpTransceiver | 收发对的捆绑体 | 关联方向、编解码与收发器 |
| Candidate | 一条候选线路 | host、srflx、relay 三类 |
| SSRC | 媒体流的同步源标识 | 每条 RTP 流的数字身份 |
| MID | 媒体段标识 | BUNDLE 复用时区分流归属 |
| DataChannel | 数据通道 | 跑在 SCTP 上的可靠或不可靠通道 |
几个容易混淆的关系值得一说。Track 与流的关系:早期模型里媒体流是容器,轨道装在流里交换;新模型里交换以收发器为单位,流退化为分组标签。Sender 与 Transceiver 的关系:发送句柄管"把这条轨道发出去",收发器管"这对资源按什么方向工作",方向可以是只收、只发或双向,协商中可能变化。Candidate 的三类来路:host 是本机网卡直接给出的地址,srflx 是经由 STUN 服务器探测到的公网映射地址,relay 是 TURN 中转服务器分配的地址——三者的取舍与优先级在第三章会专门展开。
背景。团队新来一位同事接手联调,抓了一份两浏览器直连通话的抓包文件,满屏都是 UDP 小包,有的一来一回节奏极快,有的间隔二十毫秒连续不断,他分不清哪些是"话",哪些是"管话的话"。
操作。我们让他按三个特征归堆:看包长与载荷首字节特征,看时间节奏,看方向与数量关系。包长不到百字节、成对出现且内容高度相似的是 STUN 交互——连通性检查与保活;载荷首字节的高两位固定为十、长度中等、间隔约二十毫秒连续下行的是 RTP 媒体包;同样规律但低频出现、包内携带统计结构的是 RTCP 报告;建连初期的几轮证书交换形态明显不同,那是 DTLS 握手。
结果。归堆之后,整份抓包呈现清晰的三段式:前几秒的穿越与握手流量,占比极小但决定成败;随后的媒体洪流,RTP 与 RTCP 混跑,流量占绝对大头;偶尔插入的带宽探测突发,短时间密度陡增。三类流量在时间轴上几乎不打架,说明打洞成功后走了直连。
解读。这个练习的价值在于把第一节的表格变成直觉:信令流量不在抓包里,因为它走应用自建的通道;STUN 与 DTLS 是"接通阶段"的产物;RTP 与 RTCP 是"通话阶段"的产物。遇到建连失败,先盯前段;遇到画质劣化,先盯后段。抓包分析的第一步从来不是看懂每个字节,而是分对堆。
变式。如果这次通话打洞失败、走了 TURN 中转,抓包形态会完全改观:所有媒体与 STUN 流量都封装在与中转服务器之间的同一条五元组里,端到端地址藏在中转封装内层,三段式消失,只剩两台终端各自与中转服务器的持续对话。这也是排查中转流量时要先看服务端日志的原因——线索在内层,不在外层。
常见误区有三个。一是以为信令也是 WebRTC 的一部分,于是去源码里找信令服务器——找不到的,信令从第一天起就是应用的责任。二是把媒体流当成交换的最小单位,按旧模型写代码,结果在新版浏览器上行为对不上——记住新模型以收发器为中心。三是把 SSRC 理解为连接标识,实际上它标识的是流,一条连接上音视频各有多条流,还有专门用于重传的流,第七章会看到它们的分工。
本节要点:协议族五层表是全书的检索索引,信令不标准是特性不是缺陷,安全密钥不走信令是端到端加密的根基,三类候选与收发器模型是第三章和第五章反复出场的主角。下一节我们把源码真正拉到本地,让这些名词落到能编译、能断点的实体上。