二、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 进行屏幕共享

媒体获取 体验