WebRTC 核心概念详解
本文系统梳理 WebRTC 的五大核心概念:信令、SDP、ICE/STUN/TURN、DTLS+SRTP、GCC 拥塞控制,并深入讲解 NAT 穿透原理和 GCC 算法细节。
缩写全称速查
| 缩写 | 全称 | 中文 |
|---|---|---|
| SDP | Session Description Protocol | 会话描述协议 |
| ICE | Interactive Connectivity Establishment | 交互式连接建立 |
| STUN | Session Traversal Utilities for NAT | NAT 会话穿越工具 |
| TURN | Traversal Using Relays around NAT | 通过中继穿越 NAT |
| DTLS | Datagram Transport Layer Security | 数据报传输层安全协议 |
| SRTP | Secure Real-time Transport Protocol | 安全实时传输协议 |
| RTP | Real-time Transport Protocol | 实时传输协议 |
| RTCP | RTP Control Protocol | RTP 控制协议 |
| GCC | Google Congestion Control | 谷歌拥塞控制算法 |
| NAT | Network Address Translation | 网络地址转换 |
| TLS | Transport Layer Security | 传输层安全协议 |
| UDP | User Datagram Protocol | 用户数据报协议 |
| TCP | Transmission Control Protocol | 传输控制协议 |
| NACK | Negative Acknowledgement | 否定确认(丢包重传请求) |
| FEC | Forward Error Correction | 前向纠错 |
| REMB | Receiver Estimated Maximum Bitrate | 接收端估计最大码率 |
| BWE | Bandwidth Estimation | 带宽估计 |
一、信令(Signaling)
一句话:WebRTC 两端想通话,但双方都不知道对方在哪、能用什么格式——信令就是用来交换这些「元信息」的通道。
比喻:你要和朋友打电话,但没有存他号码。你们先互发微信消息「我的号码是 xxx,你的是多少?」——这个过程就是信令。
关键点:
- WebRTC 不规定信令用什么协议,随便你用 WebSocket、HTTP、甚至短信
- 信令只传两类内容:SDP(我能做什么)和 ICE Candidate(我在哪)
- 信令服务器本身不碰媒体流,只是个「中间人」转发消息
1 | A ──── Offer SDP ────→ 信令服务器 ──→ B |
信令与 SDP 的关系
一句话:SDP 是信令传递的内容,信令是传递 SDP 的通道。
- 信令 = 快递公司(负责把东西送到)
- SDP = 快递里装的其中一封信(具体内容)
信令负责传递两类东西:
1 | ① SDP(Offer / Answer)—— 「我能做什么」(编解码器、分辨率等能力) |
SDP 是其中一类,不是全部。两类都传完,连接才能建立。
完整时序如下:
1 | A 信令服务器 B |
二、SDP(Session Description Protocol)
一句话:我把自己的「能力清单」写给你看——我支持哪些编解码器、用什么分辨率、监听哪个端口。
比喻:相亲前双方交换简历,写清楚「我身高 180、会做饭、有房」,对方看完说「OK 我接受,我的情况是 xxx」。
真实的 SDP 长这样(截取片段):
1 | v=0 |
Offer / Answer 模型:
1 | A 发 Offer:「我支持 VP8 和 H264,你选一个」 |
三、ICE / STUN / TURN
核心问题:互联网上大多数设备在 NAT 后面(路由器后),没有公网 IP,两端怎么直连?
3.1 STUN 和 TURN 的本质区别
- STUN:照镜子,告诉你自己的公网地址是什么,不转发流量
- TURN:快递柜,P2P 打不通时帮你中转所有流量
| STUN | TURN | |
|---|---|---|
| 作用 | 告诉你「你家门牌号是 xxx」 | 帮你把信收下,再转交给朋友 |
| 流量过服务器吗 | 不过,只是查询 | 所有流量都过 |
| 费用 | 极低(只有查询请求) | 高(要承载所有音视频流量) |
| 使用时机 | 每次连接都用 | 仅 P2P 打不通时兜底 |
3.2 STUN——「你的公网地址是什么」
1 | 你(192.168.1.100:12345) |
3.3 ICE——「尝试所有路径,找最优的一条」
| 类型 | 是什么 | 优先级 |
|---|---|---|
| host | 本机局域网 IP | 最高(同局域网直连) |
| srflx | 通过 STUN 拿到的公网 IP | 中(NAT 穿透) |
| relay | TURN 服务器中继地址 | 最低(兜底) |
1 | ① 先试 host candidate(局域网直连)→ 最快 |
3.4 TURN——「P2P 打不通时的中继」
走 TURN 就是走公网服务器代理所有媒体流:
1 | P2P 直连:手机A ──────────────────────→ 手机B |
影响:
- 延迟增加 20-100ms
- 带宽成本高(服务器承载完整媒体流)
- 内容安全:SRTP 加密,TURN 只转发密文
生产环境策略: 能直连绝不走 TURN;TURN 使用率超 30% 说明打洞成功率偏低需排查。
代码里只需配置地址,其余全自动:
1 | val iceServers = listOf( |
四、NAT 深挖
4.1 NAT 是什么
IPv4 地址只有 43 亿个,NAT 让一个公网 IP 后面可以藏几百台设备:
1 | 你的手机(192.168.1.100:12345) |
4.2 NAT 四种类型
① 完全锥型(Full Cone):任何人都能主动发包进来,穿透最容易 ★☆☆☆
② 地址限制锥型(Address Restricted):只有 A 发过包的目标 IP 才能回包 ★★☆☆
③ 端口限制锥型(Port Restricted):只有 A 发过包的目标 IP+Port 才能回包 ★★★☆
④ 对称型(Symmetric):每次发往不同目标,分配不同公网端口,最难穿透 ★★★★
4.3 P2P 打洞原理
两端同时向对方发包,让路由器 NAT 表留下记录:
1 | ② A 向 B 的公网地址发包 → NAT-A 留记录(允许 B 回包)→ NAT-B 无记录,丢弃 |
关键:两端必须同时发包,信令服务器负责协调。
4.4 对称型 NAT 打不通的原因
1 | A 通过 STUN 拿到端口 5678(只对 STUN 服务器有效) |
现实中 P2P 打洞成功率约 70-80%,剩下 20-30% 靠 TURN 兜底。
五、DTLS + SRTP
WebRTC 所有媒体流强制加密,不能关。
| 层 | 协议 | 作用 |
|---|---|---|
| 密钥交换 | DTLS | 基于 UDP 的 TLS,握手交换加密密钥 |
| 媒体加密 | SRTP | 用 DTLS 协商的密钥加密每一帧音视频 |
1 | 1. ICE 建立 UDP 连接 |
用 DTLS 不用 TLS 的原因:RTP 跑在 UDP 上,TLS 依赖 TCP,DTLS 是能在 UDP 上工作的版本。
六、GCC 拥塞控制深挖
两个并行估计器,取最小值:
1 | ┌── 基于延迟的估计器(Trendline Filter)──┐ |
6.1 延迟梯度估计器(Trendline Filter)
延迟梯度 δ = 到达间隔 - 发送间隔
1 | δ > 0 → 队列积压(拥塞) |
用线性回归拟合趋势,过滤抖动噪声,状态机判断:
1 | NORMAL → OVERUSE(持续上升)→ UNDERUSE(下降)→ NORMAL |
AIMD 码率调整:
1 | UNDERUSE → 每秒 +8%(慢慢探测上限) |
6.2 丢包率估计器(Loss-based)
1 | 丢包率 < 2% → 码率 ×1.08 |
6.3 为什么两个都需要
| 延迟梯度 | 丢包率 | |
|---|---|---|
| 响应速度 | 快(队列刚积压就感知) | 慢(等包真的丢了) |
| 准确性 | 受抖动影响,有误判 | 准确 |
取最小值 = 保守策略,哪个说降就降。
6.4 完整闭环
1 | 发送端 ── RTP包(带时间戳)──────────────→ 接收端 |
现代 WebRTC 用 Transport-CC(发送端自己算延迟梯度),比老的 REMB 更精准。
七、串起来看整个流程
1 | 1. A 和 B 各自通过 STUN 拿到自己的公网地址 |
最后更新:2026-06