ICE Candidateとは、WebRTCインフラの要素で、デバイス間のP2P接続を確立するための潜在的なネットワークアドレス(IP + ポート)を表します。各候補は、メディアデータの転送に使用可能なトランスポートパスを記述します。ICE(Interactive Connectivity Establishment)プロセスでは、デバイスが候補リストを交換し、テストして最適なルートを選択します。Mozilla MDN, 2026によると、ICE Candidateは複雑なネットワーク環境での接続を確保するWebRTCスタックの重要なコンポーネントです。
ポイント
ICE Candidate(Interactive Connectivity Establishment Candidate)は、WebRTCプロトコルによるP2P接続確立プロセスにおける基本的な単位です。これは2つのピア間でデータ転送に使用できるIPアドレスとポートのペアを表します。各候補は、トランスポートプロトコル(UDP、TCP)、接続タイプ、および優先度に関する情報を含みます。
ICE Candidateは各デバイスで個別に形成されます。デバイスは利用可能なすべてのネットワークインターフェースを収集し、STUNサーバーを介して外部アドレスを要求し、TURNサーバーからリレーアドレスを追加します。取得した候補リストは、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)仕様に記載されています。
多くのモバイルアプリ開発者は、Google WebRTC(Android用)やiOS用のネイティブラッパーなどのWebRTCライブラリを使用しています。それぞれにおいてICEプロセスは自動的に管理されますが、候補のタイプを理解することで、開発者はサーバーインフラを構成し、接続品質を最適化できます。
ICE CandidateはSDPメッセージ内でa=candidate属性として転送されます。各行には、foundation、component ID、トランスポートプロトコル、優先度、IPアドレス、ポート、候補タイプが含まれます。以下は、異なるタイプの3つの候補を含む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仕様は4つのタイプの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に記述されており、候補の収集、並べ替え、テスト、指名の4つの必須フェーズを含みます。
各デバイスは利用可能なすべてのネットワークアドレスを収集します。WebRTCエンジンはローカルインターフェース(host)を列挙し、STUNサーバーにリクエストを送信し(srflx)、TURNサーバーにリレーアドレスを要求します。同時に、デバイスはピアから着信STUNリクエストを受信するとprflx候補を検出する場合があります。
モバイル開発では、この段階は接続確立時間に重要です。iOSおよびAndroidでは、候補収集にかかる時間は、ネットワーク速度、STUN/TURNサーバーの可用性、アクティブなネットワークインターフェースの数に応じて、200msから2秒の範囲です。
シグナリングチャネルを介してリモートピアから候補リストを受信した後、ローカルICEエンジンはすべての可能な候補ペア(ローカル+リモート)を形成します。各ペアは、RFC 8445の式に従って、両方の候補の優先度と方向(incoming/outgoing)を考慮した優先度を取得します。
ペアは優先度の降順に並べ替えられます。最良のペアが最初にテストされます。このアルゴリズムは、host-hostペアがhost-srflx、host-relay、relay-relayよりも先にチェックされ、単純なネットワーク構成での接続遅延を最小限に抑えることを保証します。
ICEは各候補ペアにSTUN-bindingリクエストを送信します。STUN応答を受信すると、ペアは有効と見なされます。最初の有効なペアがnominated(指名)され、プライマリとして設定されます。WebRTCエンジンはこのペアを介してメディアの転送を開始し、残りのペアはプライマリが故障した場合に備えて引き続きチェックされます。
テストプロセスは、候補が多い場合に数秒かかることがあります。WebRTCはタイマーを使用します。hostペアはアグレッシブなタイマー(20ms)、relayはより保守的なタイマー(200ms)です。モバイルアプリ開発者は、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サーバーにより、デバイスはNATが発信接続に割り当てたパブリックIPアドレスとポートを確認できます。STUNプロトコルはRFC 8489で定義され、UDPポート3478で動作し、TCPもサポートします。Googleは無料で使用できるパブリックSTUNサーバー(stun.l.google.com:19302)を提供しています。
モバイル開発では、STUNリクエストは50~200msの軽量な操作です。ただし、一部の企業およびモバイルネットワークはUDPトラフィックをブロックするため、ICEはSTUN通信にTCPを使用するか、すぐにTURNに移行する必要があります。
TURNサーバーはメディアトラフィックの中継器です。直接P2P接続が不可能な場合(対称NAT、ファイアウォール)、デバイスはデータをTURNに送信し、TURNが別のピアに転送します。TURNは信頼性が高いですがコストのかかるメカニズムで、レイテンシ(30~100ms)を追加し、全メディアセッションの合計に等しい帯域幅を必要とします。
WebRTC Stats Report(2025)によると、モバイルネットワークでのWebRTCセッションの約8~15%がTURNを必要とします。TURNトラフィックのコストを最適化するために、開発者は事前接続テストを使用し、P2Pが失敗した場合のみTURNチャネルをアクティブにします。
モバイルプロジェクトのICEインフラストラクチャを選択する際には、レイテンシを最小限に抑えるためのサーバーの地理的な場所、UDPとTCPのサポート、TURNトラフィックのコスト、SLAを考慮します。人気のソリューション: セルフホスト用のcoturn、クラウド用のTwilio、Agora、LiveKit。
モバイル開発者にとってICE Candidateの理解は理論を超え、音声通話やビデオ通話を備えたアプリケーションを作成する際の実用的な必要性です。iOSおよびAndroidプラットフォームはICEを自動化するネイティブAPIを提供していますが、開発者は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モードはすべてのメディアストリームを1つのトランスポートに統合し、候補の総数を削減して接続を高速化します。
開発者が処理すべき主要なICEイベント: ICE接続状態、ICE収集状態の変更、新しい候補の検出です。ICEが収集とテストを完了すると、その状態はconnectedまたはcompletedに移行します。
モバイルネットワークでは、WiFiとセルラー間の切り替えが頻繁に発生します。ネットワーク変更時にICEがrestartを実行しないと、メディアストリームが中断されます。開発者は、NetworkManager(iOS)またはConnectivityManager(Android)の監視を実装して、restartIce()を自動的に呼び出します。
モバイルアプリケーションでのICEの成功実装には以下が含まれます: 信頼性の高いSTUN/TURNサーバーの選択、ネットワーク変更時のICE restartの適切な処理、接続状態のUI表示のためのiceConnectionState設定、RTCStatsReportを介した統計情報の監視。
よくある質問
ICE Candidateは、WebRTC通話の“試用アドレス”です。友人に電話する必要があるが、どこにいるかわからないと想像してください。自宅(host)、共通の知人(STUN)、配達員(TURN)を介して連絡を試みます。それぞれの方法がICE Candidateです。
RFC 8445仕様は4つのタイプを定義しています: host(ローカルインターフェース)、srflx(STUNによる外部アドレス)、prflx(ピアからの動的候補)、relay(TURNサーバー上のアドレス)。各タイプには独自の優先度と検出メカニズムがあります。
STUNはP2P接続のために自身の外部IPアドレスを確認するのに役立ちますが、データ転送には関与しません。TURNは直接P2P接続が不可能な場合にメディアトラフィックを中継するリレーです。TURNはレイテンシを追加し、サーバーの帯域幅を消費します。
ICE restartはネットワークの変更(WiFiからモバイルインターネットへの切り替え)、接続の喪失、またはセッションの有効期限切れ時に必要です。再起動時に、現在のすべての候補がリセットされ、ICEは新しいufragとpwdで収集を再開します。
WebRTCでは、RTCPeerConnectionでgetStats()メソッドを使用します。これにより、candidateTypeフィールドを含むRTCStatsReportが返されます。AndroidおよびiOSでは、アクティブなICE候補、そのタイプ、選択されたペアのRTTに関する統計を取得できます。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。