二、WebRTC 工作流程:信令、SDP、ICE/STUN/TURN 全流程解析

WebRTC基础 精选 3 分钟 |
二、WebRTC 工作流程:信令、SDP、ICE/STUN/TURN 全流程解析

WebRTC 的工作流程

WebRTC 的工作流程主要包括以下几个步骤:

  1. 媒体捕获:使用 MediaStream API 捕获音频和视频。
  2. 信令:WebRTC 本身不指定信令协议,但需要开发者实现自己的信令机制(通常使用 WebSocket 或 REST API)来交换元数据,如 SDP 描述符和 ICE 候选。信令服务器负责发现对方、管理房间信息,并转发媒体和网络信息。
  3. 建立连接:通过 RTCPeerConnection 建立一个对等(Peer-to-Peer)连接。
    • 媒体协商:通过 SDP 交换彼此的音视频编解码能力,确保双方能正确编解码。
    • NAT 穿透:利用 ICE 框架,通过 STUN 服务器发现公网地址,若失败则通过 TURN 服务器中继流量,以应对不同的 NAT 类型。ICE 候选者有优先级之分,包括主机候选者(本地局域网 IP)、反射候选者(NAT 后的外网 IP)和中继候选者(TURN 服务器中转地址)。
  4. 数据交换:RTCDataChannel 允许对等端之间通过建立的连接交换数据。

流程图:端到端连接建立概览

flowchart LR
  A[本地浏览器\ngetUserMedia 捕获媒体] --> B[信令通道\n使用 WebSocket 或 HTTP]
  A --> C[创建 RTCPeerConnection]
  C --> D[创建 SDP Offer]
  D -->|通过信令发送| E[远端浏览器]
  E --> F[设置远端 SDP\n并创建 Answer]
  F -->|通过信令返回| C
  C --> G[ICE 候选收集\n含 STUN 查询]
  G -->|发送候选| E
  E -->|回传候选| C
  C --> H{能否直连}
  H -->|是| I[建立 P2P 直连\n媒体与数据直传]
  H -->|否| J[通过 TURN 中继\n建立连接]
  I --> K[媒体流与数据通道\n稳定传输]
  J --> K

以上流程图概览了从本地媒体采集、SDP 协商、ICE/STUN/TURN 选择到最终媒体/数据传输的关键步骤。

时序图:SDP/ICE 信令交换

sequenceDiagram
  %% SDP/ICE 详细时序
  participant L as 本地浏览器
  participant S as 信令服务器
  participant R as 远端浏览器

  Note over L: getUserMedia() 获取音视频轨道
  L->>L: new RTCPeerConnection()
  L->>L: addTrack()/addTransceiver()
  L->>L: createOffer() / setLocalDescription(offer)
  L->>S: 发送 SDP Offer
  S->>R: 转发 SDP Offer
  R->>R: setRemoteDescription(offer)
  R->>R: createAnswer() / setLocalDescription(answer)
  R->>S: 发送 SDP Answer
  S->>L: 转发 SDP Answer
  L->>L: setRemoteDescription(answer)

  par ICE 候选交换
    L->>L: 收集本地 ICE 候选(含 STUN 外网候选)
    L->>S: 发送 ICE 候选
    S->>R: 转发 ICE 候选
    R->>S: 回传 ICE 候选
    S->>L: 转发 ICE 候选
  end

  alt 直连成功
    L-->>R: 建立 P2P 媒体/数据通道
  else 直连失败
    L-->>R: 通过 TURN 中继完成连接
  end

上述时序图聚焦于通过信令服务器交换 SDP 与 ICE 候选的过程,展示了典型的一次通话建立所需的关键往返。

更直白的理解

信令 / SDP

  • 信令是“打招呼”和“约定怎么聊”。
  • SDP 就是“我能说什么、怎么看视频”的清单(编解码器、分辨率等)。

ICE / STUN / TURN

  • 先走直连,走不通就查公网地址(STUN),再不行走中转(TURN)。
  • 直连延迟低;中转更稳但贵。

媒体 vs 数据通道

  • 音视频像直播;
  • DataChannel 像对讲机或快递:要么快一点、丢点包没事;要么严格到齐、顺序到达。

最小示例

仅演示流程,真实项目需要信令服务端。

// 关键步骤示例
const pc = new RTCPeerConnection();
const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
stream.getTracks().forEach(t => pc.addTrack(t, stream));

const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
signaling.send({ type: 'offer', sdp: offer.sdp });

pc.onicecandidate = (e) => e.candidate &&
  signaling.send({ type: 'candidate', candidate: e.candidate });

signaling.on('answer', async ({ sdp }) =>
  pc.setRemoteDescription({ type: 'answer', sdp })
);

const dc = pc.createDataChannel('chat', { ordered: false });
dc.onopen = () => dc.send('hi');

标签

#WebRTC #工作流程 #实时通信 #P2P #ICE #STUN #TURN #SDP #RTCPeerConnection #RTCDataChannel

版权声明

本文由 WebRTC.link 创作,采用 CC BY-NC-SA 4.0 许可协议。本站转载文章会注明来源以及作者。如果您需要转载,请注明出处以及作者。

评论区

Giscus

评论由 Giscus 驱动,基于 GitHub Discussions

相关文章

探索更多相关内容,深入了解 WebRTC 技术的各个方面

演示 Demo

LIVE

基础摄像头访问

展示如何使用 getUserMedia API 获取摄像头和麦克风

媒体获取 体验

PTZ 摄像头控制

控制支持 PTZ 功能的摄像头进行平移、倾斜和缩放

媒体获取 体验

屏幕共享

使用 getDisplayMedia API 进行屏幕共享

媒体获取 体验