WebRTC的信令过程是怎样的?为什么需要信令服务器?
WebRTC的信令过程是怎样的?为什么需要信令服务器?
WebRTC 本身只负责音视频采集、编解码和点对点传输,但在两个浏览器建立直连之前,它们需要先交换一些关键信息——这个过程就叫信令(Signaling)。信令是 WebRTC 连接建立的前置环节,没有它,两个隔离在各自网络里的浏览器根本找不到对方。
信令过程的核心步骤
信令过程可以拆成两个并行的子流程:SDP 协商和 ICE 候选交换。它们不是串行的,而是几乎同时进行。
SDP 协商:双方就"用什么格式通话"达成一致
- 呼叫方创建
RTCPeerConnection,调用createOffer()生成 SDP Offer - 呼叫方调用
setLocalDescription()保存本地描述,然后通过信令服务器将 Offer 转发给应答方 - 应答方收到 Offer 后调用
setRemoteDescription()设置远端描述 - 应答方调用
createAnswer()生成 SDP Answer,再通过信令服务器回传 - 呼叫方收到 Answer 后调用
setRemoteDescription()完成协商
SDP 里包含了什么?媒体格式(编解码器、payload type)、带宽限制、ICE 账号密码、DTLS 指纹等。双方通过 Offer/Answer 交换这些信息,选出共同支持的编码方案。
ICE 候选交换:双方就"通过哪条网络路径连接"达成一致
- 双方创建
RTCPeerConnection后,ICE Agent 开始收集候选地址 - 每发现一个候选,触发
onicecandidate事件,通过信令服务器发送给对方 - 对方收到后调用
addIceCandidate()添加候选
ICE 候选有三种类型:
- Host 候选:本机网卡地址,优先级最高
- Server Reflexive 候选(srflx):通过 STUN 服务器获取的公网映射地址
- Relay 候选(relay):TURN 服务器分配的中继地址,优先级最低但穿透能力最强
实际项目中常用 Trickle ICE 策略:不等所有候选收集完毕,而是找到一个就发一个,加快连接速度。
连接建立
SDP 协商和 ICE 候选交换完成后,ICE 会对候选对进行连通性检查。一旦找到可用的路径,DTLS 握手随即完成,SRTP 通道建立,双方开始传输音视频数据。
为什么需要信令服务器?
WebRTC 规范故意不定义信令协议,但信令服务器在连接建立中不可或缺,原因如下:
NAT 穿透的必要条件
大多数设备在 NAT 或防火墙后面,无法直接被外部访问。信令服务器是双方交换 ICE 候选的唯一通道——没有它,两个浏览器根本不知道对方的公网地址和端口,也无法协调 STUN/TURN 的使用。
媒体协商的桥梁
两个浏览器支持的编解码器可能不同(比如 Chrome 支持 VP8/VP9/AV1,Safari 可能只支持 H.264)。SDP 协商让双方在连接建立前就确定好共同支持的编码方案,避免连接成功却发现无法解码的尴尬。
会话状态管理
实际应用中还需要处理房间创建、用户加入/离开、通话挂断等业务逻辑。这些都不在 WebRTC 规范内,需要信令服务器配合业务层实现。
安全认证的起点
DTLS 证书指纹通过 SDP 传递,确保连接建立后双方可以验证对方身份。如果指纹不匹配,连接会被拒绝。信令服务器是这个信任链的传输通道。
信令协议怎么选?
WebRTC 不限制信令协议,常见的选型:
- WebSocket:最主流的方案,全双工、低延迟,适合实时通信场景
- Socket.io:在 WebSocket 基础上加了房间、广播等语义,开发效率高
- HTTP 轮询:实时性差,仅作为降级方案
生产环境建议使用 WSS(加密的 WebSocket),防止信令数据被截获或篡改。
常见踩坑
- 忘记在
setRemoteDescription之前设置好ontrack等事件监听,导致远端流丢失 - ICE 候选在 SDP 协商完成前到达,调用
addIceCandidate()会报错,需要做缓冲处理 - 信令服务器只存在单进程内存中,服务器重启所有房间丢失,建议用 Redis 共享会话状态