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 可用性出问题。
写段代码
jsconst 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)