videocalling
信令(Signaling)

信令(Signaling)

技术

在建立连接之前协调 WebRTC 对等点之间通信的过程

什么是信令?

\n

信令是允许两个 WebRTC 对等点相互发现并交换建立直接点对点连接所需信息的过程。可以把信令想象成初次打电话约见面——你还没到见面地点,只是在协调在哪里、什么时候见面。

\n

当你想与某人开始视频通话时,你的浏览器并不神奇地知道对方的 IP 地址、支持什么视频编解码器,或如何穿过防火墙到达对方。信令就是在 WebRTC 建立实际媒体连接之前,在两个对等点之间交换这些关键设置信息的信使服务。

\n

有趣的是,WebRTC 刻意没有规定信令应该如何工作。你可以使用 WebSocket、HTTP 长轮询、服务器推送事件,甚至信鸽——WebRTC 不在乎。这种灵活性是有意为之,允许开发者将 WebRTC 集成到现有架构和通信系统中。

\n\n

为什么需要信令

\n

WebRTC 实现点对点连接,意味着你的浏览器直接与对方的浏览器通话,媒体不经过服务器(大多数情况下)。但这里有个悖论:要建立直接连接,两个对等点首先需要了解对方。

\n

你的 WebRTC 客户端最初一无所知。它不知道:

\n
    \n
  • 你想连接谁
  • \n
  • 对方在哪里(IP 地址)
  • \n
  • 对方支持什么媒体格式(编解码器)
  • \n
  • 如何穿过 NAT/防火墙到达对方
  • \n
  • 安全通信使用什么加密密钥
  • \n
\n

信令提供了一个中立的会面地点——信令服务器——双方对等点可以在此交换这些引导信息。一旦他们拥有足够的对方信息,就可以尝试建立直接连接,信令服务器的工作就完成了(尽管它通常保持可用以协调通话期间的变化)。

\n\n

信令工作原理:提供/应答交互

\n

WebRTC 信令遵循一种称为提供/应答模型的模式,借鉴自 SIP(会话初始协议)。以下是分步过程:

\n\n

1. 对等点 A 创建提供

\n

发起通话的对等点(对等点 A)通过在其 RTCPeerConnection 对象上调用 createOffer() 创建 SDP 提供。此提供包含:

\n
    \n
  • 支持的音频和视频编解码器(H.264、VP8、VP9、Opus 等)
  • \n
  • 媒体能力(分辨率、帧率)
  • \n
  • 加密密钥(用于保护连接的 DTLS 指纹)
  • \n
  • 网络传输详情
  • \n
  • 会话元数据
  • \n
\n

提供格式化为 SDP(会话描述协议),一种基于文本的格式,看起来像这样:

\n
v=0\no=- 123456789 2 IN IP4 127.0.0.1\ns=-\nt=0 0\na=group:BUNDLE 0 1\nm=audio 9 UDP/TLS/RTP/SAVPF 111 103\nc=IN IP4 0.0.0.0\na=rtcp:9 IN IP4 0.0.0.0\na=ice-ufrag:abcd\na=ice-pwd:efgh1234\na=rtpmap:111 opus/48000/2\nm=video 9 UDP/TLS/RTP/SAVPF 96 97\na=rtpmap:96 VP8/90000\n...
\n\n

2. 通过信令通道发送提供

\n

对等点 A 将此提供设置为其本地描述(setLocalDescription())并通过信令通道发送给对等点 B。这可以是 WebSocket 消息、HTTP POST 请求、消息队列——应用程序用于信令的任何方式。

\n

关键的是,信令服务器不需要理解 SDP 内容。它只是将一段文本从对等点 A 传递到对等点 B。SDP 对信令基础设施来说是"黑盒子"。

\n\n

3. 对等点 B 接收并处理提供

\n

对等点 B 通过信令通道接收提供并将其设置为远程描述(setRemoteDescription())。浏览器解析 SDP 以了解对等点 A 的能力以及他们为通话提议的内容。

\n\n

4. 对等点 B 创建应答

\n

对等点 B 通过调用 createAnswer() 创建 SDP 应答。此应答通过以下方式响应提供:

\n
    \n
  • 从提供的编解码器中选择兼容的(拒绝不支持的)
  • \n
  • 确认接受哪些媒体流
  • \n
  • 提供自己的加密密钥
  • \n
  • 添加网络传输详情
  • \n
\n\n

5. 发送应答

\n

对等点 B 将此应答设置为其本地描述并通过信令通道发送回对等点 A。对等点 A 接收它并将其设置为远程描述。

\n\n

6. ICE 候选交换

\n

在提供/应答交换发生的同时,双方对等点都在收集 ICE 候选——连接的潜在网络路径。每次对等点发现一个候选(本地 IP、来自 STUN 的公网 IP、来自 TURN 的中继地址)时,他们通过信令将其发送给对方。

\n

这称为"涓流 ICE"——候选在发现时就发送,而不是等待所有候选后再发送。这显著加快了连接建立速度,通常将设置时间从 5-10 秒减少到 1 秒以内。

\n\n

7. 建立连接

\n

一旦双方对等点拥有彼此的 SDP 和足够的 ICE 候选,ICE 执行连接性检查并建立最佳的点对点路径。媒体开始在对等点之间直接流动,信令通道对媒体本身不再需要(尽管它通常保持可用以进行通话控制,如添加参与者或结束通话)。

\n\n

什么是 SDP?

\n

会话描述协议(Session Description Protocol,简称 SDP)是 WebRTC 提供和应答使用的格式。SDP 在 RFC 8866 中定义,是一种基于文本的协议,最初设计用于描述多媒体会话。虽然看起来神秘,但它是人类可读的,遵循简单的键=值格式。

\n

SDP 消息包含:

\n
    \n
  • 会话级信息:会话名称、时间、连接数据
  • \n
  • 媒体描述:每种媒体类型一个(音频、视频、数据通道)
  • \n
  • 属性:编解码器详情、加密、ICE 参数、传输协议
  • \n
\n

每个媒体描述(m= 行)按优先级顺序列出编解码器。例如,m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 表示这是支持三种编解码器的视频流,ID 为 96、97 和 98(VP8、VP9、H.264 等,在后续 rtpmap 属性中指定)。

\n

虽然你很少需要手动解析 SDP(浏览器处理它),但理解其结构有助于调试连接问题和优化编解码器选择。

\n\n

常见信令协议

\n

由于 WebRTC 没有标准化信令,开发者可以自由选择最适合其应用的方式:

\n\n

WebSocket(最常见)

\n

WebSocket 通过单个 TCP 连接提供全双工、实时、双向通信。它是 WebRTC 信令的事实标准,因为:

\n
    \n
  • 低延迟(持久连接,无重连开销)
  • \n
  • 高效的实时信令(从服务器立即推送到客户端)
  • \n
  • Socket.IO、ws、uWebSockets 等库支持良好
  • \n
  • 自然适合涓流 ICE(在候选被发现时流式传输)
  • \n
\n

大多数生产级 WebRTC 应用使用 WebSocket 进行信令。

\n\n

HTTP(REST + 轮询或 SSE)

\n

基于 HTTP 的信令使用 REST API 发送消息,使用轮询或服务器推送事件(SSE)接收消息。虽然不如 WebSocket 高效,但它可以穿过可能阻止 WebSocket 的严格企业防火墙。

\n

WHIP(WebRTC-HTTP 接入协议)和 WHEP(WebRTC-HTTP 输出协议)是使用简单 HTTP POST 请求进行信令的现代 IETF 标准,特别适用于广播场景。

\n\n

自定义/专有协议

\n

一些应用使用现有的消息基础设施:

\n
    \n
  • XMPP/Jingle(扩展现有聊天协议的消息应用)
  • \n
  • SIP(与传统 VoIP 基础设施集成)
  • \n
  • MQTT(物联网应用)
  • \n
  • 自定义消息队列(RabbitMQ、Redis Pub/Sub)
  • \n
\n\n

信令服务器的角色

\n

信令服务器通常处理:

\n
    \n
  1. 用户在线状态:跟踪哪些用户在线并可进行通话
  2. \n
  3. 房间/会话管理:创建和管理通话房间,处理谁可以加入
  4. \n
  5. 消息路由:在对等点之间中继 SDP 提供、应答和 ICE 候选
  6. \n
  7. 身份验证:验证用户有权发起或加入通话
  8. \n
  9. 通话控制:协调静音/取消静音、添加参与者、屏幕共享、结束通话等事件
  10. \n
\n

信令服务器也是实现业务逻辑的地方:用户权限、录制触发器、计费事件、分析等。虽然它不处理媒体,但它是整个视频通话系统的控制平面。

\n\n

不同架构中的信令

\n\n

点对点

\n

在纯 P2P 中,信令服务器只帮助对等点找到彼此并交换初始连接数据。一旦连接,对等点直接通信。信令服务器可以在通话中途离线而不影响媒体质量。

\n\n

SFU(选择性转发单元)

\n

使用 SFU 时,信令变得更复杂。服务器必须协调:

\n
    \n
  • 每个客户端与 SFU 的连接(不是点对点)
  • \n
  • 每个参与者订阅哪些流
  • \n
  • 联播层选择
  • \n
  • 参与者改变视图时的动态流路由
  • \n
\n

SFU 信令比 P2P 更复杂,通常使用超越基本 SDP 交换的自定义协议。

\n\n

MCU(多点控制单元)

\n

MCU 信令在某些方面更简单——每个客户端连接到 MCU 服务器,接收一个合成流,信令服务器管理谁在会议中。MCU 在服务器端处理所有混合,因此信令专注于房间管理而不是复杂的流路由。

\n\n

安全考虑

\n\n

使用安全传输

\n

始终使用 WSS(安全 WebSocket)或 HTTPS,而不是普通 WS 或 HTTP。SDP 包含加密指纹,但如果信令通道本身未加密,攻击者可以通过修改 SDP 执行中间人攻击。

\n\n

验证信令消息

\n

验证用户有权发送提供、加入房间或访问某些通话。实施基于令牌的身份验证(JWT 是常见的),并在每条信令消息上验证令牌,而不仅仅是初始连接。

\n\n

速率限制

\n

信令服务器容易受到 DoS 攻击。恶意客户端可能会用提供或加入请求轰炸服务器。对每个用户/IP 实施速率限制以防止滥用。

\n\n

验证 SDP

\n

虽然将 SDP 视为黑盒子,但你仍然可以验证基本合理性:大小限制(典型 SDP 为 2-10KB,任何巨大的都可疑)、正确格式、合理数量的媒体行。这可以防止试图利用 SDP 解析器的攻击。

\n\n

调试信令问题

\n

当 WebRTC 连接失败时,信令通常是罪魁祸首:

\n
    \n
  • 连接永远不启动:检查 SDP 提供/应答是否交换。使用浏览器开发者工具的网络标签验证信令消息到达
  • \n
  • "设置远程描述失败"错误:SDP 格式错误或不兼容。检查编解码器协商,确保双方对等点至少支持一种通用编解码器
  • \n
  • ICE 候选未到达:信令通道可能不支持涓流 ICE 消息,或候选中继逻辑存在错误
  • \n
  • 连接有时有效有时无效:信令中的竞态条件。确保正确顺序:setLocalDescription → 发送提供 → 接收应答 → setRemoteDescription
  • \n
\n

Chrome 的 chrome://webrtc-internals 显示完整的信令交换,包括 SDP 内容和时间,对调试非常宝贵。

\n\n

现代发展(2025 年)

\n\n

WHIP/WHEP

\n

WebRTC-HTTP 接入协议(WHIP)和 WebRTC-HTTP 输出协议(WHEP)为广播用例标准化了基于 HTTP 的信令。它们将信令复杂性降低到简单的 HTTP POST 请求,非常适合将流接入到 CDN 或云服务。

\n

2025 年采用率正在增长,特别是在传统 WebSocket 信令过于复杂的直播和广播场景中。

\n\n

去中心化信令

\n

一些项目探索使用 DHT(分布式哈希表)、区块链或对等发现协议的去中心化信令。虽然在理论上有趣,但对于 2025 年的生产应用来说,集中式信令服务器仍然更实用和可靠。

\n\n

总结

\n

信令是 WebRTC 的无名编舞者。虽然它不传输媒体,但它通过协调初始握手使整个点对点连接成为可能。理解信令对于调试 WebRTC 问题、实现安全的视频通话和扩展基础设施至关重要。

\n

WebRTC 刻意不标准化信令是一种优势,而不是劣势。它允许你将 WebRTC 集成到任何现有系统中——无论你是为聊天应用添加视频、构建远程医疗平台还是创建游戏语音聊天功能。你可以重用现有的身份验证、消息基础设施和业务逻辑。

\n

信令服务器是你应用独特身份所在的地方。WebRTC 连接可能是标准化的,但信令是你区分产品的地方。

\n\n

参考资料

\n