ICE 与 STUN/TURN:STUN Binding 请求、TURN 分配与转发、中继候选者的协商
各位同学,今天我们来聊聊 WebRTC 里最“接地气”但又最容易踩坑的部分——ICE 与 STUN/TURN。说实话,我刚开始接触 WebRTC 时,觉得 ICE 就是个黑盒子,STUN 和 TURN 更是傻傻分不清。直到有一次在项目中,用户视频死活连不上,我才真正开始啃这块硬骨头。
嗯,咱们今天就把这层窗户纸捅破。说白了,ICE 就是帮两个浏览器找到一条能通的路,而 STUN 和 TURN 就是这条路上的“导航员”和“中转站”。
1. STUN Binding 请求:我是谁?我在哪?
先说说 STUN。STUN 的全称是 Session Traversal Utilities for NAT,名字挺长,但干的事很简单——帮你找到自己的公网 IP 和端口。
你想想看,你的电脑在局域网里,IP 是 192.168.1.x,但外面的人想找你,得知道你的公网 IP。STUN 服务器就是干这个的:你发一个 Binding 请求过去,服务器看看这个请求是从哪个公网 IP 和端口来的,然后原封不动告诉你。
核心要点:STUN Binding 请求是 ICE 候选者收集的第一步。没有它,你连自己“长什么样”都不知道。
我在项目中遇到过一个问题:客户端发 STUN 请求后,拿到的公网 IP 和实际不符。后来发现是 NAT 类型太严格,STUN 返回的映射地址只在当前会话有效。嗯,这里要注意,STUN 不是万能的,它只适用于锥形 NAT。
2. TURN 分配与转发:最后的保底方案
当 STUN 搞不定时,TURN 就上场了。TURN 的全称是 Traversal Using Relays around NAT,说白了就是“我帮你转一下”。
TURN 的工作流程分两步:
- 分配:客户端向 TURN 服务器发 Allocate 请求,服务器分配一个中继地址(Relay Address)给你。
- 转发:你的媒体数据先发给 TURN 服务器,服务器再转发给对端。
我个人习惯把 TURN 比作“快递中转站”。你寄快递,不是直接送到收件人手里,而是先到中转站,再由中转站派送。代价就是——慢,而且贵(服务器带宽要钱啊)。
避坑指南:我曾经在项目中只配了 STUN,没配 TURN,结果在对称 NAT 环境下,用户全部连不上。后来紧急上了 TURN,才解决问题。记住:TURN 是保底方案,但必须配。
3. 中继候选者的协商:ICE 的最终决策
ICE 收集候选者时,会得到三种类型:
- Host 候选者:本机 IP,局域网内可用。
- Srflx 候选者:STUN 拿到的公网 IP。
- Relay 候选者:TURN 分配的中继地址。
ICE 的协商过程,说白了就是“先试快的,不行再试慢的”。优先级从高到低是:Host > Srflx > Relay。ICE 会按优先级排序,然后两两测试连通性。
为什么会这样?因为 Host 候选者延迟最低,Relay 候选者延迟最高。你想想看,如果两个人在同一个局域网,直接用 Host 候选者多快,何必绕一圈 TURN?
下面这张图展示了 ICE 候选者收集和协商的完整流程:
从图中可以看到,客户端 A 先通过 STUN 拿到自己的公网 IP(Srflx 候选者),如果不行,再通过 TURN 拿到中继地址(Relay 候选者)。然后 ICE 把所有候选者排序,逐一测试连通性,最终选出一条能用的路。
小技巧:在实际开发中,我建议你优先使用 STUN,只有在 STUN 失败时才回退到 TURN。这样可以节省 TURN 服务器的带宽成本。另外,TURN 服务器的带宽是按流量计费的,别让所有用户都走 TURN。
4. 实战中的注意事项
最后,分享几个我在项目中踩过的坑:
- STUN 超时:有些网络环境会丢包,STUN 请求超时后要重试,一般重试 3 次。
- TURN 认证:TURN 服务器通常需要用户名和密码,别硬编码在客户端,建议动态获取。
- 候选者优先级:ICE 的优先级计算有公式,但记住一点——Host 永远最高,Relay 永远最低。
- ICE 重启:如果网络切换(比如从 WiFi 切到 4G),需要重新收集候选者,别复用旧的。
嗯,今天就讲到这里。ICE 与 STUN/TURN 这块内容,说白了就是“找路”和“借路”。理解了这一点,后面的媒体协商就顺理成章了。