ICE Candidate — це елемент інфраструктури WebRTC, який являє собою потенційну мережеву адресу (IP + порт) для встановлення P2P-з'єднання між пристроями. Кожен кандидат описує доступний транспортний шлях, який може бути використаний для передачі медіаданих. У процесі ICE (Interactive Connectivity Establishment) пристрої обмінюються списками кандидатів, тестують їх і обирають оптимальний маршрут. За даними Mozilla MDN, 2026, ICE Candidate є ключовим компонентом WebRTC-стека, що забезпечує з'єднання у складних мережевих умовах.
Головне
ICE Candidate (Interactive Connectivity Establishment Candidate) — це фундаментальна одиниця у процесі встановлення P2P-з'єднання за протоколом WebRTC. Він являє собою пару IP-адреса + порт, яка може бути використана для передачі даних між двома пірами. Кожен кандидат містить інформацію про транспортний протокол (UDP, TCP), тип з'єднання та пріоритет.
ICE Candidate формується на кожному пристрої окремо. Пристрій збирає всі доступні мережеві інтерфейси, запитує зовнішню адресу через STUN-сервер і додає relay-адресу від TURN-сервера. Отриманий список кандидатів надсилається віддаленому піру через signalling-канал у форматі SDP (Session Description Protocol).
За специфікацією RFC 8445 (IETF, 2018), ICE використовує механізм nominated pairs: після збору всіх кандидатів виконується їх попарне тестування через STUN-запити. Пара, яка пройшла перевірку першою, оголошується nominated (призначеною) і використовується для передачі мультимедіа. Інші пари залишаються в резерві на випадок розриву з'єднання.
WebRTC — це відкритий стандарт для P2P-комунікацій, але пряме з'єднання між пристроями часто неможливе через NAT (Network Address Translation) і файрволи. ICE Candidate вирішує цю проблему, пропонуючи кілька альтернативних шляхів з'єднання. Протокол ICE (Interactive Connectivity Establishment) є обов'язковим компонентом WebRTC і описаний у специфікації W3C WebRTC (2025).
Багато розробників мобільних застосунків використовують WebRTC-бібліотеки, такі як Google WebRTC (для Android) і native-обгортки для iOS. У кожній з них процес ICE керується автоматично, але розуміння типів кандидатів дозволяє розробнику налаштовувати серверну інфраструктуру та оптимізувати якість з'єднання.
ICE Candidate передається у складі SDP-повідомлення у вигляді атрибутів a=candidate. Кожен рядок містить foundation, component ID, транспортний протокол, пріоритет, IP-адресу, порт і тип кандидата. Нижче наведено приклад SDP-фрагмента з трьома кандидатами різних типів:
// Приклад SDP з ICE кандидатами
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 | Середній | Peer-рефлексія (у процесі ICE) | Ні |
| relay | Найнижчий | TURN-сервер | TURN |
Host кандидат формується з IP-адреси локального мережевого інтерфейсу пристрою. Якщо пристрій перебуває в одній локальній мережі з піром, host-кандидат забезпечує пряме з'єднання з мінімальною затримкою. Для мобільних пристроїв host-кандидати генеруються для WiFi-інтерфейсу, стільникового LTE/5G-з'єднання та за потреби — для VPN-тунелів.
Host-кандидати мають найвищий пріоритет (2130706431 для UDP) і тестуються першими. Якщо обидва піри перебувають за NAT, їх host-кандидати будуть приватними адресами (192.168.x.x, 10.x.x.x), і пряме з'єднання за ними неможливе. ICE переходить до тестування srflx і relay кандидатів.
SRFLX (Server Reflexive) кандидат — це зовнішня IP-адреса і порт, отримані від STUN-сервера. Коли пристрій надсилає STUN-запит, сервер бачить його публічну адресу після NAT і повертає її назад. Цей кандидат дозволяє встановити пряме з'єднання між пірами за різними NAT, якщо їх NAT-пристрої підтримують Hairpinning.
PRFLX (Peer Reflexive) кандидат виявляється динамічно, коли STUN-запит від одного піра приходить на несподівану адресу. Цей тип виникає, коли обидва піри надсилають запити одночасно, і NAT створює тимчасове зв'язування. PRFLX кандидат має вищий пріоритет, ніж srflx, але нижчий, ніж host.
У мобільних застосунках srflx-кандидати особливо важливі під час перемикання між WiFi і стільниковою мережею. Коли пристрій змінює мережу, IP-адреса змінюється, і ICE має перезібрати кандидатів. Цей процес називається ICE restart і потребує повторного надсилання нового SDP.
Relay кандидат — це адреса на TURN-сервері, через яку трафік ретранслюється від одного піра до іншого. Цей тип використовується як запасний варіант, коли пряме P2P-з'єднання неможливе (симетричний NAT, корпоративний файрвол). Relay-канал додає затримку і збільшує навантаження на сервер, тому в оптимальних налаштуваннях TURN-сервер використовується лише для 10–15% усіх сесій.
Популярні реалізації TURN-серверів: coturn (відкритий код), Twilio Network Traversal, Metered TURN. Вибір TURN-провайдера впливає на якість медіаз'єднання у мобільних застосунках — сервер має розташовуватися географічно близько до користувачів, щоб мінімізувати додаткову затримку.
Процес ICE — це багатоетапний протокол, який гарантує встановлення надійного P2P-з'єднання в умовах невизначеності мережевої топології. Алгоритм описаний у RFC 8445 і включає чотири обов'язкові фази: збір кандидатів, їх сортування, тестування та номінація.
Кожен пристрій збирає всі доступні мережеві адреси. Для цього WebRTC-движок перелічує локальні інтерфейси (host), надсилає запит на STUN-сервер (srflx) і запитує relay-адресу у TURN-сервера. Одночасно пристрій може виявити prflx-кандидата, якщо отримає вхідний STUN-запит від піра.
У мобільній розробці цей етап критичний для часу встановлення з'єднання. На iOS і Android збір кандидатів може займати від 200 мс до 2 секунд залежно від швидкості мережі, доступності STUN/TURN серверів і кількості активних мережевих інтерфейсів.
Після отримання списку кандидатів від віддаленого піра через signalling-канал локальний ICE-движок формує всі можливі пари кандидатів (локальний + віддалений). Кожна пара отримує пріоритет за формулою з RFC 8445, що враховує пріоритети обох кандидатів і напрямок (incoming/outgoing).
Пари сортуються за спаданням пріоритету. Найкращі пари тестуються першими. Алгоритм гарантує, що host-host пара буде перевірена раніше, ніж host-srflx, host-relay або relay-relay, мінімізуючи затримку з'єднання у простих мережевих конфігураціях.
ICE надсилає STUN-binding-запити для кожної пари кандидатів. Якщо STUN-відповідь отримана — пара дійсна. Перша дійсна пара номінується (nominated) як основна. WebRTC-движок починає передавати медіа за цією парою, а інші пари продовжують перевірятися на випадок відмови основної.
Процес тестування може зайняти до кількох секунд за великої кількості кандидатів. WebRTC використовує таймери: для host-пар таймер агресивний (20 мс), для relay — консервативніший (200 мс). Розробники мобільних застосунків можуть прискорити з'єднання, обмеживши кількість ICE-серверів або налаштувавши iceTransportPolicy.
ICE restart — це перезапуск процесу ICE без перестворення всього RTCPeerConnection. Він необхідний при зміні мережі, втраті з'єднання або перемиканні між WiFi і мобільною мережею. При restart усі поточні кандидати скидаються, і процес починається заново з генерації нового ufrag і pwd.
У iOS розробці ICE restart викликається методом restartIce() на RTCPeerConnection. На Android використовується аналогічний метод у класі PeerConnection з Google WebRTC. Коректна обробка 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 — надійний, але затратний механізм: він додає затримку (30–100 мс) і потребує пропускної здатності сервера, що дорівнює сумі всіх медіасесій.
За даними WebRTC Stats Report (2025), близько 8–15% WebRTC-сесій у мобільних мережах потребують TURN. Для оптимізації витрат на TURN-трафік розробники використовують попереднє тестування з'єднання і лише при невдачі P2P активують TURN-канал.
Під час вибору інфраструктури для ICE в мобільному проєкті враховуються: географічне розташування серверів для мінімізації затримки, підтримка UDP і TCP, вартість TURN-трафіку та SLA. Популярні рішення: coturn для самостійного встановлення, Twilio, Agora та LiveKit для хмарного використання.
Для мобільних розробників розуміння ICE Candidate виходить за межі теорії — це практична необхідність під час створення застосунків з голосовими та відеодзвінками. Платформи iOS і Android надають нативні API для WebRTC, які автоматизують роботу з ICE, але розробник відповідає за конфігурацію ICE-серверів і обробку подій зміни мережі.
На iOS WebRTC доступний через фреймворк WebRTC.framework або бібліотеку GoogleWebRTC через CocoaPods. ICE-сервери конфігуруються через масив RTCIceServer у RTCConfiguration:
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. Розробник може керувати політикою ICE через iceTransportsType — режим 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 допомагає дізнатися свою зовнішню IP-адресу для P2P-з'єднання, але не бере участі в передачі даних. TURN — це ретранслятор, який передає медіатрафік через себе, коли пряме P2P-з'єднання неможливе. TURN додає затримку і споживає пропускну здатність сервера.
ICE restart необхідний при зміні мережі (перемикання з WiFi на мобільний інтернет), втраті з'єднання або завершенні часу сесії. При restart усі поточні кандидати скидаються, і ICE починає збір заново з новими ufrag і pwd.
У WebRTC використовуйте метод getStats() на RTCPeerConnection, який повертає RTCStatsReport з полем candidateType. На Android і iOS можна отримати статистику щодо активного ICE кандидата, його типу та RTT для вибраної пари.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.