WebRTC 如何让网页实现端到端的通信
码不停提
WebRTC:让网页拥有“超能力”,实现实时端到端通信
码不停提
WebRTC:让网页拥有“超能力”,实现实时端到端通信
想象一下,当你想通过网页和好友视频聊天时,通常需要下载一个软件(如Skype、Zoom)或插件。而WebRTC就是为了打破这个限制而生。
WebRTC的整个过程可以类比为两位陌生人准备通过一个安全的秘密隧道直接通话。这需要三个关键步骤:
具体到技术层面,这由三大API和两种服务器角色实现:
这是前端开发者直接使用的工具。
getUserMedia: 获取“麦克风”和“摄像头”的访问权限。这是获取音视频流的起点。RTCPeerConnection: 核心中的核心。它负责在两端的浏览器之间建立并维护那个高效的、加密的“点对点连接通道”,处理所有复杂的音视频编码、网络传输等工作。RTCDataChannel: 在已建立的RTCPeerConnection通道上,再开一个数据传输的小通道。你可以用它来发送任何二进制或文本数据(比如聊天文字、文件),实现一个“端到端加密的聊天室”。这些服务器只负责“牵线搭桥”,不负责传递通话内容本身,因此它们无法窃听。
让我们通过一个经典的“A呼叫B”的例子,看看这些部分如何协同工作。
flowchart TD
A[用户A<br>发起通话] --> B[调用 getUserMedia<br>获取本地音视频流]
B --> C[创建 RTCPeerConnection 对象]
C --> D[创建“邀约” Offer<br>并设置本地流]
D -- 通过信令服务器转发 --> E{用户B<br>接受通话}
E --> F[调用 getUserMedia<br>获取本地音视频流]
F --> G[创建 RTCPeerConnection 对象]
G --> H[收到“邀约”<br>创建“应答” Answer]
H -- 通过信令服务器转发 --> I
subgraph I [关键交互:网络协商与连接]
direction LR
J[A与B交换<br>ICE候选地址] --> K[通过STUN/TURN服务器<br>探测连通性]
K --> L[建立最佳P2P连接]
end
L --> M[连接成功!<br>开始加密的端到端通话/数据传输]
下面,我们来拆解上图中信令交换和网络协商这两个关键环节:
步骤 1 & 2:发起邀约与接受应答
createOffer 生成一个包含其媒体信息和加密密钥的 “邀约” 。A将此 offer 通过信令服务器发给B。offer 后,调用 createAnswer 生成一个 “应答” 。B将此 answer 通过信令服务器发回给A。这就是“交换接头方式”。
offer和answer里包含了双方的“能力清单”(如支持哪些编解码器)和加密密钥的“种子”。
步骤 3:交换网络“地图”
offer/answer 的同时,A和B的浏览器会各自通过询问STUN服务器,获知自己的公网IP和端口,这些地址称为 ICE候选。步骤 4:开始通信
RTCPeerConnection 状态变为“已连接”时,那个安全的秘密隧道就建好了。RTCDataChannel 在这个隧道里开一个数据小通道。这是WebRTC设计精妙之处,也是对开篇问题的直接回答:
RTCPeerConnection 使用 DTLS(用于数据)和 SRTP(用于音视频)协议对数据进行端到端加密。加密密钥只在交换 offer/answer 时由双方生成和共享,信令服务器只能看到加密后的密钥“种子”,无法算出真正的密钥。因此,一个标准实现的WebRTC应用,后台无法监控聊天内容。除非应用本身在客户端做了手脚(例如,在本地录制并上传日志),但这已超出了WebRTC协议本身的范围。
以下是一个极度简化的代码片段,展示了如何使用 RTCPeerConnection 的核心方法。
// 假设我们已经通过信令服务器(signaling)建立了连接
const signaling = new SignalingChannel(); // 你的WebSocket连接
const pc = new RTCPeerConnection();
// 1. 当有远程流到来时,显示在video标签里
pc.ontrack = (event) => {
document.getElementById('remoteVideo').srcObject = event.streams[0];
};
// 2. 发起方:创建邀约
async function createOffer() {
// 获取本地媒体流(需要用户授权)
const localStream = await navigator.mediaDevices.getUserMedia({video: true, audio: true});
localStream.getTracks().forEach(track => pc.addTrack(track, localStream));
const offer = await pc.createOffer();
await pc.setLocalDescription(offer); // 设置本地描述
signaling.send({type: 'offer', sdp: offer.sdp}); // 通过信令发送
}
// 3. 接收方:处理邀约并应答
signaling.onMessage(async (message) => {
if (message.type === 'offer') {
// 设置远程描述(对方的邀约)
await pc.setRemoteDescription(new RTCSessionDescription(message));
// 获取本地流并添加
const localStream = await navigator.mediaDevices.getUserMedia({video: true, audio: true});
localStream.getTracks().forEach(track => pc.addTrack(track, localStream));
// 创建并发送应答
const answer = await pc.createAnswer();
await pc.setLocalDescription(answer);
signaling.send({type: 'answer', sdp: answer.sdp});
}
});
// 4. 发起方:处理应答
signaling.onMessage(async (message) => {
if (message.type === 'answer') {
await pc.setRemoteDescription(new RTCSessionDescription(message));
}
});
希望这份文档能帮你建立起对WebRTC清晰、直观的理解。如果你想深入了解信令服务器的具体搭建方法,或 RTCDataChannel 的使用细节,我可以为你提供进一步的资料。
本站提供了一个 WebRTC 的 MVP,可以立即体验 https://rx.sc.cn/dev-tools/rtc

补充介绍:🌐 STUN/TURN服务器:WebRTC的“网络向导”与“备用桥梁”
简单来说,STUN/TURN服务器是帮助WebRTC在复杂网络世界中建立直接连接的关键后台服务。它们本身不传递通话内容,而是专门解决“两个设备如何找到并连通彼此”这个难题。
想象一下,你(浏览器A)和朋友(浏览器B)各自住在一个有门卫和复杂内部结构的公寓楼(局域网)里,你们想直接对话。
192.168.1.10)。203.0.113.1 的端口 55000。”203.0.113.1:55000 就是你在这个特定连接中的公网可访问地址(即ICE候选地址之一)。你将这个地址通过信令服务器告诉对方,对方就可以尝试向这个地址发送数据,建立直接连接。WebRTC使用一个称为 ICE框架 的机制来自动选择最佳连接路径。STUN和TURN服务器是提供ICE候选地址的关键来源。
flowchart TD
A[WebRTC连接开始] --> B
subgraph B [ICE候选地址收集阶段]
direction LR
C[收集主机候选地址<br>(本地IP)]
D[向STUN服务器查询<br>获取服务器反射候选地址]
E[向TURN服务器申请<br>获取中继候选地址]
end
B --> F[通过信令服务器<br>交换所有候选地址列表]
F --> G{ICE连接性检查<br>尝试按顺序连通}
G --> H{成功?}
H -- ✅ 是 --> I[选择最佳路径<br>(通常优先级:主机 > 反射 > 中继)]
H -- ❌ 否 --> J[尝试列表中下一个候选地址对]
J --> G
I --> K[建立P2P连接<br>开始加密通信]
路径选择优先级:
| 特性 | STUN服务器 | TURN服务器 |
|---|---|---|
| 核心作用 | 发现设备的公网地址和端口 | 在无法直连时,中继所有数据 |
| 是否转发媒体 | 否(仅协助连接) | 是(所有数据都经它中转) |
| 资源消耗 | 极低(仅处理少量请求) | 高(转发全部音视频流,占用带宽) |
| 成本 | 通常有免费公共服务 | 通常需付费(因消耗带宽) |
| 对隐私的影响 | 无影响(不接触媒体流) | 不破坏端到端加密(转发加密数据) |
你需要知道的:
stun:stun.l.google.com:19302)进行测试。但对于TURN,由于资源消耗大,公共服务很少,产品上线时需要自己搭建或购买商业服务(如Twilio Network Traversal Service、Agora等)。简单来说,STUN/TURN服务器是WebRTC连接得以成功的无名英雄。它们处理了网络底层的复杂性,让开发者可以专注于应用功能,让用户能享受一键即通的实时通信体验。
暂无目录