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 候选者选择流程。你看完应该能明白,为什么有时候连接快,有时候慢。

ICE 候选者选择流程 开始收集候选者 收集 host 候选者(本机 IP) 收集 srflx 候选者(STUN) 收集 relay 候选者(TURN) 按优先级排序,从高到低尝试 优先级说明 host:最高(126) srflx:中等(100) relay:最低(0) ICE 会先试 host 失败后降级到 srflx 最后才用 relay

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,先扫一眼候选者列表,问题往往就暴露了。

公众号:蓝海资料掘金营,微信deep3321