2、WebRTC核心架构:P2P通信模型、信令与媒体流分离、NAT穿透与ICE框架、SDP协商机制

WebRTC 的架构设计,说白了就是一套「让浏览器之间能直接通话」的工程方案。我最早接触它的时候,觉得这东西简直像变魔术——两个在不同内网里的浏览器,怎么就能互相传视频呢?后来拆开一看,其实核心就四块:P2P 模型、信令与媒体分离、NAT 穿透、SDP 协商。咱们一个一个聊。

2.1 P2P 通信模型:为什么非要「点对点」?

传统的视频通话,通常是客户端-服务器模式。你说话,声音先到服务器,服务器再转发给对方。这模式简单,但服务器带宽成本高得吓人。我见过一个创业团队,用户量刚破万,服务器带宽费就占了营收的 60%。

WebRTC 走的是 P2P 路线。说白了,就是你的浏览器直接连对方的浏览器,数据不经过中间服务器。好处很明显:

  • 延迟低:少跳一次网络,延迟能降 30-50ms
  • 成本省:服务器只负责「牵线」,不负责「传话」
  • 隐私好:数据不落地,加密传输

但 P2P 也有坑。我在项目中遇到过一个问题:两个用户都在对称 NAT 后面,直接连根本连不上。这时候就得靠 TURN 服务器做中继了。嗯,这里要注意——P2P 是理想,实际场景里经常退化成 TURN 中继。

核心要点:WebRTC 优先尝试 P2P,失败后自动降级为 TURN 中继。开发者不需要手动干预,ICE 框架会帮你搞定。

2.2 信令与媒体流分离:为什么非要「分家」?

WebRTC 有一个设计让很多人困惑:它把「信令」和「媒体流」完全分开。信令走你自己搭的服务器(WebSocket、HTTP 都行),媒体流走 P2P 通道。

为什么会这样?我个人的理解是:WebRTC 不想替开发者决定用什么信令协议。你想想看,有的团队用 SIP,有的用 XMPP,有的自己写 JSON 协议。WebRTC 要是把信令也标准化了,反而限制了灵活性。

信令负责什么?说白了就三件事:

  1. 交换 SDP:告诉对方「我支持什么编码、我的 IP 是什么」
  2. 交换 ICE 候选:告诉对方「我有哪些可能的连接路径」
  3. 控制会话:谁发起、谁挂断、要不要静音

媒体流负责什么?就是真正的音视频数据。走的是 SRTP/SCTP 协议,加密传输。

我的建议:信令服务器用 WebSocket 实现最简单。别用 HTTP 轮询,延迟太高。我曾经见过一个项目用 HTTP 长轮询做信令,结果信令延迟比媒体流还大,通话建立要 5 秒以上。

2.3 NAT 穿透与 ICE 框架:最难啃的骨头

NAT 穿透,这是 WebRTC 里最让我头疼的部分。你想想,全世界有几十种 NAT 设备,每种的行为都不一样。有的 NAT 会随机分配端口,有的会限制外部连接,有的还会检测协议类型。

ICE 框架就是用来解决这个问题的。它整合了三种技术:

技术 原理 成功率 我的经验
STUN 问服务器「我的公网 IP 和端口是多少」 约 70% 大部分家用路由器都能过
TURN 通过服务器中继数据 接近 100% 带宽成本高,慎用
mDNS 局域网内直接发现 局域网内 100% 适合同 WiFi 场景

ICE 的工作流程是这样的:

  1. 收集所有可能的候选地址(本地 IP、公网 IP、TURN 地址)
  2. 按优先级排序(P2P 优先,TURN 兜底)
  3. 双方交换候选列表
  4. 尝试连接,直到成功

避坑指南:我曾经在部署时忘了开 TURN 服务器的 3478 端口,结果所有用户都连不上。排查了整整一天才发现是防火墙的问题。记住,STUN 和 TURN 的端口一定要在防火墙里放行。

下面这张图展示了 ICE 框架的完整流程:

ICE 框架工作流程 Peer A Peer B STUN / TURN 服务器 ① 收集候选 ① 收集候选 ② 信令服务器交换候选 ③ 连通性检查 ③ 连通性检查 ④ P2P 连接建立(或 TURN 中继) ⑤ 音视频媒体流传输(SRTP 加密)

2.4 SDP 协商机制:双方「握手」的协议

SDP 全称是 Session Description Protocol,翻译过来就是「会话描述协议」。它不负责传输数据,只负责描述「这次通话要用什么参数」。我习惯把它理解成「通话前的体检报告」。

SDP 里包含哪些信息?我列几个关键的:

  • 媒体类型:音频、视频、还是数据通道
  • 编解码器:H.264、VP8、Opus 等
  • 网络信息:IP 地址、端口号
  • 传输协议:RTP、SRTP、UDP、TCP
  • 带宽限制:最大码率、分辨率

SDP 协商的过程,说白了就是「Offer/Answer」模型:

  1. 发起方(Offerer)生成一个 SDP,描述自己支持的参数
  2. 通过信令通道发给接收方(Answerer)
  3. 接收方解析 SDP,匹配双方都支持的参数
  4. 接收方生成 Answer SDP,发回给发起方
  5. 双方确认后,开始传输媒体流

关键点:SDP 协商必须在媒体流传输之前完成。如果协商失败,通话就建立不起来。我见过一个坑——双方都只支持 H.265,但 WebRTC 默认只支持 H.264 和 VP8,结果协商失败。后来加了 H.264 支持才解决。

下面是一个简化的 SDP 示例:

v=0
o=- 123456 2 IN IP4 192.168.1.100
s=-
t=0 0
m=audio 49170 RTP/AVP 0 8 97
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:97 opus/48000
m=video 49172 RTP/AVP 96 98
a=rtpmap:96 H264/90000
a=rtpmap:98 VP8/90000
a=fmtp:96 packetization-mode=1

这段 SDP 的意思是:音频支持 PCMU、PCMA 和 Opus,视频支持 H.264 和 VP8。接收方会从中选一个双方都支持的编解码器。

我的经验:调试 SDP 问题的时候,最有效的方法就是打印出完整的 SDP 字符串,逐行对比。我曾经花了两天时间,最后发现是 H.264 的 packetization-mode 参数不匹配导致的。记住,SDP 里每一行都很重要。

2.5 小结

WebRTC 的核心架构,说白了就是一套「让浏览器直接通话」的工程方案。P2P 模型省带宽,信令与媒体分离保灵活,ICE 框架搞定 NAT 穿透,SDP 协商确保双方能对上话。这四个部分缺一不可。

实际开发中,我建议你先把 ICE 和 SDP 的流程跑通,再考虑优化。很多新手一上来就折腾编解码器参数,结果连最基本的 P2P 连接都建立不起来。嗯,先把基础打牢,后面的事就好办了。


公众号:蓝海资料掘金营,微信deep3321