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-фрагмента с тремя кандидатами разных типов:
// Sample SDP with ICE candidates
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 года. Мы проконсультируем вас и предложим наилучшее решение.