ICE Candidate — 是WebRTC基础设施的一个元素,代表用于在设备之间建立P2P连接的潜在网络地址(IP + 端口)。每个候选描述了一条可用于传输媒体数据的可用传输路径。在ICE(Interactive Connectivity Establishment)过程中,设备交换候选列表,测试它们并选择最佳路由。根据Mozilla MDN,2026,ICE Candidate是WebRTC栈的关键组件,可在复杂网络条件下确保连接。
要点
ICE Candidate(Interactive Connectivity Establishment Candidate)— 是通过WebRTC协议建立P2P连接过程中的基本单元。它代表可用于在两个对等体之间传输数据的IP地址+端口对。每个候选包含有关传输协议(UDP、TCP)、连接类型和优先级的信息。
ICE Candidate在每个设备上单独形成。设备收集所有可用的网络接口,通过STUN服务器请求外部地址,并添加来自TURN服务器的中继地址。生成的候选列表通过信令通道以SDP(Session Description Protocol)格式发送到远程对等体。
根据RFC 8445(IETF,2018)规范,ICE使用nominated pairs机制:收集所有候选后,通过STUN请求进行成对测试。第一个通过测试的对被宣布为nominated(指定)并用于多媒体传输。其他对保留在备用状态,以防连接中断。
WebRTC是一种开放的P2P通信标准,但由于NAT(网络地址转换)和防火墙,设备之间的直接连接通常是不可能的。ICE Candidate通过提供多个替代连接路径来解决这个问题。ICE(Interactive Connectivity Establishment)协议是WebRTC的强制组件,并在W3C WebRTC(2025)规范中进行了描述。
许多移动应用开发人员使用WebRTC库,例如Google WebRTC(用于Android)和用于iOS的原生包装器。在每一个中,ICE过程都是自动管理的,但理解候选类型使开发人员能够配置服务器基础设施并优化连接质量。
ICE Candidate作为SDP消息的一部分以a=candidate属性形式传输。每行包含foundation、component ID、传输协议、优先级、IP地址、端口和候选类型。下面是一个包含三个不同类型候选的SDP片段示例:
// 带有ICE候选的SDP示例
a=candidate:1 1 UDP 2130706431 192.168.1.10 54321 typ host
a=candidate:2 1 UDP 1694498815 203.0.113.5 54322 typ srflx
a=candidate:3 1 TCP 1019212287 198.51.100.7 54323 typ relay raddr 203.0.113.5 rport 3478
priority字段确定候选的测试顺序。优先级越高,候选被检查得越早。Host候选始终具有最高优先级,relay具有最低优先级。
RFC 8445规范定义了四种类型的ICE候选,每种类型对应到达远程对等体的特定方式。候选类型影响其优先级、连接建立时间以及对服务器基础设施的要求。
| 类型 | 优先级 | 来源 | 服务器依赖 |
|---|---|---|---|
| host | 最高 | 本地网络接口 | 否 |
| srflx | 高 | STUN反射 | STUN |
| prflx | 中 | 对等反射(在ICE过程中) | 否 |
| relay | 最低 | TURN服务器 | TURN |
Host候选由设备本地网络接口的IP地址形成。如果设备与对等体位于同一本地网络中,host候选提供具有最小延迟的直接连接。对于移动设备,host候选是为WiFi接口、移动LTE/5G连接以及必要时为VPN隧道生成的。
Host候选具有最高优先级(UDP为2130706431)并首先被测试。如果两个对等体都在NAT后面,它们的host候选将是私有地址(192.168.x.x、10.x.x.x),通过它们的直接连接是不可能的。ICE转向测试srflx和relay候选。
SRFLX(Server Reflexive) — 是从STUN服务器获取的外部IP地址和端口。当设备发送STUN请求时,服务器会看到其在NAT后的公共地址并将其返回。如果它们的NAT设备支持Hairpinning,此候选允许在不同NAT后面的对等体之间建立直接连接。
PRFLX(Peer Reflexive) 是动态检测的,当来自一个对等体的STUN请求到达意外地址时。此类型在两个对等体同时发送请求且NAT创建临时绑定时出现。PRFLX候选的优先级高于srflx,但低于host。
在移动应用中,srflx候选在WiFi和蜂窝网络之间切换时尤其重要。当设备更改网络时,IP地址会变化,ICE必须重新收集候选。此过程称为ICE restart,需要重新发送新的SDP。
Relay候选 — 是TURN服务器上的地址,流量通过该地址从一个对等体中继到另一个对等体。当直接P2P连接不可能时(对称NAT、企业防火墙),此类型用作备用选项。中继通道会增加延迟并增加服务器负载,因此在最佳设置中,TURN服务器仅用于10–15%的所有会话。
流行的TURN服务器实现:coturn(开源)、Twilio Network Traversal、Metered TURN。TURN提供商的选择影响移动应用中的媒体连接质量 — 服务器应在地理上靠近用户,以最大程度地减少额外延迟。
ICE过程是一个多阶段协议,可保证在网络拓扑不确定的条件下建立可靠的P2P连接。该算法在RFC 8445中描述,包括四个强制阶段:收集候选、排序、测试和指定。
每个设备收集所有可用的网络地址。为此,WebRTC引擎枚举本地接口(host),向STUN服务器发送请求(srflx),并从TURN服务器请求中继地址(relay)。同时,如果设备收到来自对等体的传入STUN请求,它可能会检测到prflx候选。
在移动开发中,此阶段对连接建立时间至关重要。在iOS和Android上,收集候选可能需要200毫秒到2秒,具体取决于网络速度、STUN/TURN服务器的可用性以及活动网络接口的数量。
通过信令通道从远程对等体收到候选列表后,本地ICE引擎形成所有可能的候选对(本地+远程)。每个对根据RFC 8445中的公式获得优先级,该公式考虑了两个候选的优先级和方向(传入/传出)。
配对按优先级降序排序。最佳对首先被测试。该算法保证host-host对将在host-srflx、host-relay或relay-relay之前被检查,从而在简单网络配置中最大限度地减少连接延迟。
ICE为每个候选对发送STUN-binding请求。如果收到STUN响应 — 该对有效。第一个有效的对被指定(nominated)为主对。WebRTC引擎开始通过此对传输媒体,而其他对继续被检查,以防主对失败。
在大量候选的情况下,测试过程可能需要长达几秒。WebRTC使用定时器:对于host对使用激进定时器(20毫秒),对于relay使用更保守的定时器(200毫秒)。移动应用开发人员可以通过限制ICE服务器数量或配置iceTransportPolicy来加速连接。
ICE restart — 是在不重新创建整个RTCPeerConnection的情况下重新启动ICE过程。在网络更改、连接丢失或在WiFi和移动网络之间切换时是必需的。在重启时,所有当前候选被重置,过程从生成新的ufrag和pwd重新开始。
在iOS开发中,ICE restart通过RTCPeerConnection上的restartIce()方法调用。在Android上,使用Google WebRTC中PeerConnection类的类似方法。正确处理ICE restart — 对于在网络连接不稳定的移动设备上运行的应用程序是关键要求。
STUN(Session Traversal Utilities for NAT)和TURN(Traversal Using Relays around NAT)是关键服务器组件,没有它们,ICE Candidate无法在真实的互联网条件下保证成功连接。它们的正确配置直接影响移动应用中的通话质量。
STUN服务器允许设备了解其公共IP地址以及NAT为出站连接分配的端口。STUN协议在RFC 8489中定义,通过UDP在端口3478上工作,并支持TCP。Google提供可以免费使用的公共STUN服务器(stun.l.google.com:19302)。
在移动开发中,STUN请求是一种轻量级操作,耗时50–200毫秒。然而,一些企业和移动网络会阻止UDP流量,迫使ICE使用TCP进行STUN通信或直接切换到TURN。
TURN服务器 — 是媒体流量的中继器。当直接P2P连接不可能时(对称NAT、防火墙),设备将数据发送到TURN,TURN将其转发到另一个对等体。TURN是一种可靠但昂贵的机制:它增加了延迟(30–100毫秒),并且需要等于所有媒体会话总和的服务器带宽。
根据WebRTC统计报告(2025),移动网络中约8–15%的WebRTC会话需要TURN。为了优化TURN流量成本,开发人员使用初步连接测试,仅在P2P失败时才激活TURN通道。
在为移动项目选择ICE基础设施时,需要考虑:服务器地理位置以最小化延迟、UDP和TCP支持、TURN流量成本和SLA。流行的解决方案:coturn用于自建安装,Twilio、Agora和LiveKit用于云使用。
对于移动开发人员来说,理解ICE Candidate超越了理论范围 — 在创建具有语音和视频通话的应用程序时,这是实际需求。iOS和Android平台为WebRTC提供原生API,可自动处理ICE相关操作,但开发人员负责配置ICE服务器和处理网络更改事件。
在iOS上,WebRTC可通过WebRTC.framework框架或通过CocoaPods的GoogleWebRTC库获得。ICE服务器通过RTCConfiguration中的RTCIceServer数组配置:
let config = RTCConfiguration()
let stunServer = RTCIceServer(urlStrings: ["stun:stun.l.google.com:19302"])
let turnServer = RTCIceServer(urlStrings: ["turn:turn.example.com:3478"],
username: "user",
credential: "pass")
config.iceServers = [stunServer, turnServer]
let pc = RTCPeerConnection(configuration: config)
创建RTCPeerConnection并调用offer()或answer()后,引擎会自动收集ICE候选。iceGatheringStateChange事件通知收集状态的更改,而iceConnectionState通知连接状态。
Android使用相同的Google WebRTC库。ICE服务器通过PeerConnection.RTCConfiguration设置。开发人员可以通过iceTransportsType管理ICE策略 — relay模式强制仅使用TURN,这提高了可靠性,但也增加了延迟:
val iceServers = listOf(
PeerConnection.IceServer.builder("stun:stun.l.google.com:19302").createIceServer(),
PeerConnection.IceServer.builder("turn:turn.example.com:3478")
.setUsername("user")
.setPassword("pass")
.createIceServer()
)
val config = PeerConnection.RTCConfiguration(iceServers)
config.iceTransportsType = PeerConnection.IceTransportsType.ALL
config.bundlePolicy = PeerConnection.BundlePolicy.MAXBUNDLE
bundlePolicy参数影响ICE候选的数量 — MAXBUNDLE模式将所有媒体流合并到一个传输中,减少了候选总数并加速了连接。
开发人员应处理的关键ICE事件:ICE连接状态(ICE connection state)、收集状态的更改(ICE gathering state)以及新候选的检测。ICE完成收集和测试后,其状态转换为connected或completed。
在移动网络中,WiFi和蜂窝连接之间经常发生切换。当网络更改时,ICE必须执行restart,否则媒体流会中断。开发人员实现NetworkManager(iOS)或ConnectivityManager(Android)的监控以自动调用restartIce()。
移动应用中ICE的成功实现包括:选择可靠的STUN/TURN服务器、在网络更改时正确处理ICE restart、配置iceConnectionState以在UI中显示连接状态以及通过RTCStatsReport监控统计信息。
常见问题
ICE Candidate — 是通过WebRTC进行通话的“测试地址”。想象一下,你需要给朋友打电话,但不知道他在哪里。你尝试打电话到家(host)、通过共同认识的人(STUN)和通过快递员(TURN)。每种这样的方式都是一个ICE Candidate。
RFC 8445规范区分了四种类型:host(本地接口)、srflx(通过STUN的外部地址)、prflx(来自对等体的动态候选)和relay(TURN服务器上的地址)。每种类型都有自己的优先级和检测机制。
STUN帮助了解用于P2P连接的外部IP地址,但不参与数据传输。TURN是一种中继器,当直接P2P连接不可能时,通过自身传输媒体流量。TURN增加了延迟并消耗服务器带宽。
当网络更改(从WiFi切换到移动网络)、连接丢失或会话过期时,需要ICE restart。在重启时,所有当前候选被重置,ICE使用新的ufrag和pwd重新开始收集。
在WebRTC中,使用RTCPeerConnection上的getStats()方法,该方法返回带有candidateType字段的RTCStatsReport。在Android和iOS上,可以获取有关活动ICE候选、其类型以及所选对RTT的统计信息。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。