3、ICE 候选者调试:在 webrtc-internals 中查看 ICE 候选者类型(host/srflx/relay),分析候选者优先级
ICE 候选者,说白了就是 WebRTC 在找「连接路径」时列出的所有可能方案。你想想看,两个浏览器要建立 P2P 连接,中间可能隔着 NAT、防火墙、甚至企业 VPN,ICE 的作用就是把这些障碍一个个试过去,直到找到一条能通的路。
我个人习惯,遇到连接失败的问题,第一件事就是打开 chrome://webrtc-internals,看 ICE 候选者那一栏。为什么?因为候选者的类型和优先级,直接告诉你「这条路能不能走通」以及「系统会优先选哪条路」。
3.1 ICE 候选者的三种类型
ICE 候选者分为三类,我按优先级从高到低给你列出来:
| 类型 | 标识 | 来源 | 优先级 |
|---|---|---|---|
| host | 主机候选者 | 本机网卡 IP(局域网地址) | 最高 |
| srflx | 服务器反射候选者 | 通过 STUN 服务器获取的公网 IP | 中等 |
| relay | 中继候选者 | 通过 TURN 服务器转发 | 最低 |
嗯,这里要注意:host 候选者优先级最高,但只在局域网内有效。如果你在公网上测试,host 候选者基本是废的。我在项目中遇到过好几次,开发环境一切正常,一上生产就黑屏,最后发现是 host 候选者被优先选中了,但公网根本连不上。
核心原则:ICE 会优先尝试高优先级候选者,如果失败再降级。所以看到连接慢,先看看是不是 host 候选者浪费了时间。
3.2 在 webrtc-internals 中定位候选者信息
打开 chrome://webrtc-internals 后,找到你的 PeerConnection 会话。往下翻,你会看到 「ICE Candidate Pair」 和 「Local Candidates」 两个区域。
举个例子,我在本地抓到的候选者长这样:
// 本地候选者示例
candidate:1 1 UDP 2122252543 192.168.1.100 54321 typ host
candidate:2 1 UDP 1686052607 120.25.xx.xx 54322 typ srflx
candidate:3 1 TCP 1010822143 10.0.0.5 9 typ host tcptype active
candidate:4 1 UDP 41885439 47.92.xx.xx 3478 typ relay
每一行代表一个候选者。我来拆解一下关键字段:
- 优先级数字:越大越优先。你看 host 的 2122252543 明显比 srflx 的 1686052607 高。
- typ:候选者类型,就是 host、srflx、relay 这三个。
- IP 地址:如果是 192.168.x.x 或 10.x.x.x,基本就是 host 候选者。
- 端口:随机分配的 UDP/TCP 端口。
我的小技巧:在 webrtc-internals 里,你可以直接搜索「typ host」来快速过滤出局域网候选者。如果发现只有 host 候选者,没有 srflx 或 relay,那大概率是 STUN/TURN 服务器配置有问题。
3.3 候选者优先级是怎么算的?
你可能好奇,那个长长的数字是怎么来的。ICE 协议里有一套公式,但咱们不用背,理解逻辑就行:
优先级 = (2^24) * (type_preference) + (2^8) * (local_preference) + (2^0) * (component_id)
其中 type_preference 是核心:
- host:126(最高)
- srflx:100(中等)
- relay:0(最低)
说白了,ICE 就是靠这个数字来决定「先试哪条路」。host 候选者因为延迟最低、带宽最大,所以被优先选择。但如果你在公网环境,host 候选者根本连不上,ICE 就会降级到 srflx,最后才是 relay。
避坑指南:我曾经遇到一个线上问题,用户反馈视频通话经常卡顿。查了半天,发现 ICE 一直选的是 relay 候选者。为什么?因为用户的网络环境里,STUN 服务器被防火墙拦截了,srflx 候选者根本拿不到。最后只能走 TURN 中继,延迟高得离谱。解决方案是换了一个支持 TCP 的 STUN 服务器。
3.4 实战:用 SVG 图理解 ICE 候选者选择流程
下面这张图,是我自己画的一个 ICE 候选者选择流程。你看完应该能明白,为什么有时候连接快,有时候慢。
3.5 如何判断候选者是否正常工作?
在 webrtc-internals 里,除了看候选者列表,还要看 「ICE Candidate Pair」 区域。这里会显示当前正在使用的候选者对(本地 + 远程)。
我一般关注这几个指标:
- state:如果是
succeeded,说明这个候选者对已经连通了。 - nominated:如果是
true,说明这个候选者对已经被选中作为最终路径。 - priority:看本地和远程候选者的优先级,确认是否按预期选择了最高优先级的可用路径。
常见问题排查:
- 如果只有 host 候选者,没有 srflx 和 relay → 检查 STUN/TURN 服务器配置。
- 如果候选者列表很长但连接失败 → 可能是防火墙阻止了所有 UDP 端口,试试 TCP 候选者。
- 如果 relay 候选者优先级异常高 → 检查 TURN 服务器是否配置了
force_relay参数。
3.6 一个真实案例
我记得有一次,帮一个客户排查视频会议卡顿问题。打开 webrtc-internals 一看,候选者列表里只有 host 和 relay,没有 srflx。客户说「我们公司网络很严格,只允许 443 端口出去」。
嗯,问题就出在这里。STUN 默认用 3478 端口,被防火墙拦了。srflx 候选者拿不到,ICE 只能降级到 relay。但 relay 走的是 TURN 服务器,延迟高不说,带宽也受限。
解决方案是:在 TURN 服务器上开启 443 端口,并且配置 TCP 传输。这样 relay 候选者也能走 443 端口,至少能通。但说实话,这不是最优解,最好还是让 STUN 能正常工作。
我的建议:调试 ICE 候选者时,别只看「有没有候选者」,要看「有没有正确的候选者」。host 再多也没用,关键是 srflx 和 relay 能不能拿到。如果 srflx 拿不到,先检查 STUN 服务器可达性,用 telnet stun.example.com 3478 测一下。
好了,关于 ICE 候选者调试,核心就是这三步:看类型、看优先级、看状态。下次遇到连接问题,别慌,打开 webrtc-internals,先扫一眼候选者列表,问题往往就暴露了。