WebRTC(Web Real-Time Communication)
介绍
WebRTC 是一种基于浏览器的实时通信技术,用于在网页中实现点对点(Peer-to-Peer,P2P)通信。它是一种协议,使浏览器之间可以直接进行音视频通话、文件传输等实时数据交换。
WebRTC 的整体架构
WebRTC 架构主要分为三部分:
- Web 前端 API(紫色):提供给 Web 前端开发使用的 API。
- 浏览器厂商 API(蓝色实线):提供各大浏览器厂商使用的 API。
- 底层引擎和网络模块(蓝色虚线):包含了音频引擎,视频引擎,网络传输层(transport)。
点对点通信(Peer-to-Peer)
P2P 通信在不同网络环境的两个设备间进行,要求设备具有麦克风、摄像头等必要硬件。下面详细介绍其遇到的几个关键问题及解决方案:
问题 1:如何使设备彼此发现
需要一个中介服务器来帮助设备发现对方并交换元数据(如媒体信息、网络信息)。这一交换过程称为信令传输(Signaling),负责传输信令的服务器称为信令服务器。
问题 2:如何处理设备编解码能力不同
参与通信的设备可能支持不同的编码格式,例如,设备 A 支持 H264 和 VP8,设备 B 支持 H264 和 VP9。WebRTC 使用会话描述协议(Session Description Protocol,SDP)来解决此问题。设备在连接前交换 SDP 信息,了解对方支持的媒体格式,这一过程称为媒体协商。
问题 3:如何找到数据传输的链路
WebRTC 中的音视频数据传输依赖于网络协商。通信双方需要了解彼此的网络情况,通常会使用网络地址转换(NAT)或代理服务器将设备的局域网 IP 转为公网 IP,从而找到一条可用的通信链路。这一过程依赖中间层来建立连接(如下图),在 webrtc 中我们使用ICE 机制建立网络连接。
graph TD
subgraph 网络环境
A[设备A(局域网IP)] -->|局域网IP| B[中间层(NAT/代理服务器)]
B -->|公网IP| C[设备B(局域网IP)]
end
%% 表示网络协商的过程箭头
A -- 网络协商 --> B
B -- 网络协商 --> C
在 webrtc 中有三种类型的 ICE 候选者,按照优先级分别是:
- 主机候选者,在 WebRTC 底层,首先会尝试本地局域网内建立连接。
- 反射候选者,本地连接不通时,会尝试通过反射候选者获得的 IP 地址和端口进行连接。
- 中继候选者,通信双方无法穿越 P2P NAT 时,只能通过服务器中转数据了。
相关概念
NAT(Network Address Translation,网络地址转换)用于将局域网中的 IP 地址转换为公网 IP 地址。
ICE(Interactive Connectivity Establishment, 交互式连接建立)是一个框架,负责协调和选择最佳连接路径,以实现 NAT 穿越。 它优先通过 STUN(Session Traversal Utilities for NAT)获取设备的公网地址(就是找ip和端口的),从而建立直接的 P2P 连接。 当 STUN 无法穿越 NAT 时,TURN(Traversal Using Relays around NAT)作为备选方案,提供中继服务来保证通信的稳定性。 tips: ICE 会优先使用 STUN,仅在 STUN 失败时才会使用 TURN。
webrtc 1 对于 1 通信流程图
sequenceDiagram
participant Peer-A
participant Stun/turn服务器
participant Signal信令服务器
participant Peer-B
Note over Peer-A, Peer-B: 媒体协商
Peer-A ->> Signal信令服务器: Socket连接
Peer-B ->> Signal信令服务器: Socket连接
Peer-A ->> Peer-A: 创建PeerConnection<br>AddStream
Peer-B ->> Peer-B: 创建PeerConnection<br>AddStream
Peer-A ->> Peer-A: CreateOffer<br>SetLocalDescription
Peer-A ->> Signal信令服务器: 发送Offer信息
Signal信令服务器 ->> Peer-B: Peer-A Offer SDP
Peer-B ->> Peer-B: SetRemoteDescription
Peer-B ->> Peer-B: 创建应答:<br>CreateAnswer<br>SetLocalDescription
Peer-B ->> Signal信令服务器: 发送Answer信息
Signal信令服务器 ->> Peer-A: Peer-B Answer SDP
Peer-A ->> Peer-A: SetRemoteDescription
Note over Peer-A, Peer-B: 网络协商
Peer-A ->> Stun/turn服务器: ICE请求
Stun/turn服务器 ->> Peer-A: onIceCandidate
Peer-A ->> Signal信令服务器: 发送Candidate
Signal信令服务器 ->> Peer-B: A发送的Candidate
Peer-B ->> Peer-B: AddIceCandidate
Peer-B ->> Stun/turn服务器: ICE请求
Stun/turn服务器 ->> Peer-B: onIceCandidate
Peer-B ->> Signal信令服务器: 发送Candidate
Signal信令服务器 ->> Peer-A: B发送的Candidate
Peer-A ->> Peer-A: AddIceCandidate
Peer-B ->> Peer-A: onAddStream(B远端流)
Peer-A ->> Peer-B: onAddStream(A远端流)
tips:stun/turn服务器我们经常使用coturn开源项目来搭建的,地址是:github.com/coturn/cotu….