5月30日 00:37

WebRTC 如何实现 NAT 穿透?STUN、TURN 和 ICE 分别做什么?

WebRTC 的 NAT 穿透不是靠某一个协议硬打洞,而是由 ICE 统一调度:先收集本地地址,再用 STUN 拿到公网映射地址,最后在直连失败时走 TURN 中继。面试里可以这样答:STUN 负责“我在公网看起来是谁”,TURN 负责“直连不通时替我转发”,ICE 负责“把所有候选路径试一遍,选能通且质量最好的”。生产环境只配 STUN 不够,遇到对称 NAT、企业防火墙或 UDP 被限制时,必须有 TURN 兜底。

追问

STUN 和 TURN 有什么区别?

STUN 只参与建连阶段,帮助发现公网 IP 和端口,媒体流通常仍然点对点传输。TURN 会一直在媒体路径上转发数据,成功率高,但延迟、带宽成本和服务器压力都更大。

ICE 候选者有哪些?

常见有 host、srflx、relay 三类。host 是本机局域网地址,srflx 是 STUN 得到的公网映射地址,relay 是 TURN 分配的中继地址。

为什么有 STUN 还需要 TURN?

因为 STUN 依赖 NAT 映射可预测。对称 NAT 或严格防火墙下,对端无法直接打到这个映射端口,TURN 中继就成了最后的可用路径。

实际项目里怎么配置?

至少配置一个 STUN 和一个带鉴权的 TURN,TURN 建议靠近用户部署。监控里要看 relay 占比、ICE 失败率、连接耗时和 RTT,relay 占比突然升高通常说明网络或 STUN 可用性出问题。

写段代码

js
const pc = new RTCPeerConnection({ iceServers: [ { urls: 'stun:stun.l.google.com:19302' }, { urls: 'turn:turn.example.com:3478', username: 'u', credential: 'p' } ] }) pc.onicecandidate = e => sendToPeer(e.candidate)
标签:WebRTC