6、ICE候选者交换:ICE协议简介、候选者类型、优先级与排序、Trickle ICE机制

好,咱们今天聊一个非常核心的话题——ICE候选者交换。

我记得刚接触WebRTC那会儿,最让我头疼的就是ICE。明明两端都在同一个局域网,为什么有时候就是连不上?后来我才明白,ICE不是简单的“找地址”,而是一整套候选者发现、排序、连通性检查的体系。说白了,它解决的是“我怎么才能找到你,并且用最快的方式把数据传过去”这个问题。

6.1 ICE协议简介

ICE的全称是Interactive Connectivity Establishment,交互式连接建立。名字挺长,但核心思想很简单:让两个端点绕过NAT和防火墙,找到一条能用的通信路径

你想想看,现实中的网络环境有多复杂。有家庭路由器(NAT),有公司防火墙,有对称NAT,有端口限制型NAT……两个设备想直接通信,简直像在迷宫里找对方。ICE就是那个帮你探路的人。

ICE的工作流程大致分三步:

  1. 收集候选者:每个端点收集自己可能的通信地址(IP+端口)。
  2. 交换候选者:通过信令通道,把候选者列表发给对方。
  3. 连通性检查:两端对每一对候选者组合进行连通性测试,找到最优路径。

嗯,这里要注意:ICE不是一次性的。它会在整个会话期间持续工作,如果网络环境变了(比如你从WiFi切到了4G),ICE会重新收集和检查。

核心要点:ICE的本质是“先收集,再测试,最后选最优”。它不是猜,而是实打实地去验证每条路径能不能通。

6.2 候选者类型:host / srflx / relay

ICE候选者分三种类型,每种代表不同的“可信度”和“优先级”。

类型 缩写 来源 优先级 典型场景
主机候选者 host 本机网卡IP 最高 局域网内通信
反射候选者 srflx STUN服务器映射 中等 普通NAT穿透
中继候选者 relay TURN服务器分配 最低 对称NAT或防火墙限制

host候选者:就是你的本机IP地址。比如你电脑的192.168.1.100,或者你手机的10.0.0.2。这是最直接的地址,延迟最低,带宽最大。如果两端在同一个局域网,ICE会优先用host候选者。

srflx候选者:全称是Server Reflexive Candidate。它是通过STUN服务器获取的“公网映射地址”。举个例子,你的内网IP是192.168.1.100,经过NAT后,公网看到的可能是203.0.113.50:12345。这个地址就是srflx候选者。

我在项目中遇到过一个问题:有些NAT设备会随机分配端口,导致srflx候选者很快过期。嗯,这时候就需要频繁刷新STUN绑定,否则连接会断。

relay候选者:这是最后的保底方案。当host和srflx都走不通时(比如双方都在对称NAT后面),就只能通过TURN服务器中转数据。relay候选者延迟最高,带宽也受限,但它是“一定能通”的方案。

个人建议:在实际部署中,不要把TURN服务器当成默认方案。TURN的带宽成本很高,我见过有些团队把所有流量都走TURN,结果一个月账单吓死人。正确的做法是:优先用host,其次srflx,实在不行才用relay。

6.3 候选者优先级与排序

ICE不是随便选一个候选者就完事了。它会根据优先级对候选者进行排序,然后从高到低依次尝试连通性检查。

优先级的计算公式是这样的:

priority = (2^24) * type_preference + (2^8) * local_preference + (2^0) * component_id

其中:

  • type_preference:类型偏好,host最高(126),srflx次之(100),relay最低(0)。
  • local_preference:本地偏好,通常根据IP地址的“私密性”来定。比如,IPv6地址的local_preference比IPv4高。
  • component_id:组件ID,RTP是1,RTCP是2。

说白了,ICE会优先尝试“最有可能通”且“质量最好”的候选者组合。host候选者之间先试,不行再试srflx,最后才试relay。

我曾经踩过一个坑:在某个项目中,我们部署了多个TURN服务器,但ICE总是优先选同一个TURN节点,导致那个节点负载过高。后来发现是local_preference设置的问题——所有TURN候选者的local_preference都一样,ICE就按收到顺序选了第一个。解决办法是给每个TURN节点分配不同的local_preference,实现负载均衡。

注意:优先级只是“建议顺序”,不是“最终决定”。ICE的连通性检查会并行进行,最终选的是“第一个通过检查的候选者对”,而不是优先级最高的。所以,即使host候选者优先级最高,如果它实际上不通,ICE也会选srflx或relay。

6.4 Trickle ICE机制

传统的ICE流程是:先收集所有候选者,然后一次性通过信令发给对方,最后开始连通性检查。这个过程有个问题——慢。

你想想看,收集所有候选者需要时间。特别是relay候选者,需要跟TURN服务器交互,可能耗时几百毫秒甚至更久。如果等所有候选者都收集完再开始连接,用户体验会很差。

Trickle ICE就是解决这个问题的。它的核心思想是:边收集,边发送,边检查

具体流程是这样的:

  1. 端点A先收集到host候选者,立刻通过信令发给B。
  2. 端点B收到后,马上开始连通性检查。
  3. 同时,A继续收集srflx和relay候选者,收集到一个就发一个。
  4. B收到新的候选者后,继续补充检查。

这样一来,连接建立的时间大大缩短。大部分情况下,host候选者就能通,用户几乎感觉不到延迟。

我记得在做一个视频会议项目时,用了Trickle ICE后,连接建立时间从原来的2-3秒降到了500毫秒以内。用户体验提升非常明显。

关键点:Trickle ICE不是可选项,而是现代WebRTC的标配。如果你还在用传统的“全量收集再交换”方式,建议尽快升级。大部分WebRTC库(包括浏览器原生实现)默认都支持Trickle ICE。

知识体系图

下面这张图展示了ICE候选者交换的核心流程和关系:

ICE候选者交换核心流程 候选者收集 host(本机IP) srflx(STUN映射) relay(TURN中继) 优先级:host > srflx > relay 交换与排序 信令通道交换 优先级计算 候选者对排序 Trickle ICE:边收集边交换 连通性检查 STUN Binding请求 连通性验证 选最优路径 第一个通过的候选者对 ICE协议:收集 → 交换 → 排序 → 检查 → 连接

这张图从左到右展示了ICE的完整流程。先收集三种候选者,然后通过信令交换并排序,最后进行连通性检查。Trickle ICE让这个过程变成了流水线作业,而不是串行等待。

避坑指南:我曾经遇到过一个情况,Trickle ICE虽然快,但如果信令通道本身延迟很高(比如WebSocket连接不稳定),反而会导致候选者丢失。解决办法是在应用层加一个“候选者超时重传”机制,确保每个候选者都能可靠到达对端。

好了,关于ICE候选者交换的核心内容就这些。记住三个关键词:候选者类型(host/srflx/relay)、优先级排序Trickle ICE。理解了这些,你就掌握了WebRTC连接建立的精髓。

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