Signatur
Beschreibung
RTCIceCandidatePair ist ein einfaches Dictionary mit genau zwei Einträgen: local und remote, beide vom Typ RTCIceCandidate. Ein solches Paar beschreibt einen konkreten Netzwerkweg: Die Medien fließen von der Adresse und dem Port des lokalen Kandidaten zur Adresse und zum Port des entfernten Kandidaten.
Während des ICE-Verfahrens (Interactive Connectivity Establishment) bildet der Browser aus allen gesammelten lokalen und entfernten Kandidaten viele Paare und prüft sie per STUN auf Erreichbarkeit. Am Ende wird ein Paar ausgewählt, über das die Daten tatsächlich laufen. Dieses ausgewählte Paar bekommen Sie über RTCIceTransport.getSelectedCandidatePair(). Ändert es sich, etwa bei einem Netzwechsel oder einem ICE-Restart, wird am RTCIceTransport das Ereignis selectedcandidatepairchange ausgelöst.
In der Praxis brauchen Sie das Dictionary vor allem für Diagnose und Überwachung: Läuft die Verbindung direkt (host), über NAT-Traversal (srflx/prflx) oder über einen TURN-Server (relay)? Wird UDP oder TCP verwendet? Solche Angaben helfen bei der Fehlersuche, bei Qualitätsmetriken und bei der Kostenkontrolle für TURN-Server.
Verwechseln Sie das Dictionary nicht mit RTCIceCandidatePairStats: Diese Statistik-Einträge vom Typ "candidate-pair" stammen aus RTCPeerConnection.getStats() und enthalten Messwerte wie RTT oder übertragene Bytes, aber nur IDs der Kandidaten statt der RTCIceCandidate-Objekte selbst.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $local Pflicht | RTCIceCandidate | Der lokale ICE-Kandidat des Paares, also Adresse, Port, Protokoll und Typ (host, srflx, prflx, relay) auf der eigenen Seite. |
|
| $remote Pflicht | RTCIceCandidate | Der entfernte ICE-Kandidat des Paares, also der Endpunkt der Gegenstelle, zu dem die Daten gesendet werden. |
Rückgabewert
RTCIceTransport.getSelectedCandidatePair() liefert ein Objekt mit den Eigenschaften local und remote. Solange noch kein Paar ausgewählt wurde, ist der Rückgabewert null.Beispiele
Ausgewähltes Kandidatenpaar nach dem Verbindungsaufbau auslesen
const pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] });
pc.addEventListener('connectionstatechange', () => {
if (pc.connectionState !== 'connected') return;
const sender = pc.getSenders()[0];
const iceTransport = sender?.transport?.iceTransport;
if (!iceTransport?.getSelectedCandidatePair) {
console.warn('getSelectedCandidatePair() wird nicht unterstützt');
return;
}
const pair = iceTransport.getSelectedCandidatePair();
if (!pair) return;
const { local, remote } = pair;
console.log(`Lokal: ${local.type} ${local.protocol} ${local.address}:${local.port}`);
console.log(`Entfernt: ${remote.type} ${remote.protocol} ${remote.address}:${remote.port}`);
});
Auf Wechsel des Kandidatenpaares reagieren (z. B. WLAN → Mobilfunk)
const watchCandidatePair = (pc) => {
const iceTransport = pc.getSenders()[0]?.transport?.iceTransport;
if (!iceTransport) return;
const onChange = () => {
const pair = iceTransport.getSelectedCandidatePair();
if (!pair) return;
const viaTurn = pair.local.type === 'relay' || pair.remote.type === 'relay';
console.log(viaTurn ? 'Verbindung läuft über TURN-Relay' : 'Direkte Verbindung (P2P)');
};
// Variante 1: addEventListener
iceTransport.addEventListener('selectedcandidatepairchange', onChange);
// Variante 2: on-Property
// iceTransport.onselectedcandidatepairchange = onChange;
// Aufräumen, wenn nicht mehr benötigt
return () => iceTransport.removeEventListener('selectedcandidatepairchange', onChange);
};
Browserübergreifender Fallback über getStats()
const getActivePair = async (pc) => {
const stats = await pc.getStats();
let pairStats;
stats.forEach((report) => {
// Chrome/Safari: über den transport-Eintrag; Firefox: selected-Flag
if (report.type === 'transport' && report.selectedCandidatePairId) {
pairStats = stats.get(report.selectedCandidatePairId);
}
if (!pairStats && report.type === 'candidate-pair' && report.selected) {
pairStats = report;
}
});
if (!pairStats) return null;
const local = stats.get(pairStats.localCandidateId);
const remote = stats.get(pairStats.remoteCandidateId);
return {
local: `${local.candidateType} ${local.address}:${local.port}`,
remote: `${remote.candidateType} ${remote.address}:${remote.port}`,
rttMs: (pairStats.currentRoundTripTime ?? 0) * 1000
};
};
// Nutzung: console.log(await getActivePair(pc));
// Wichtig · Fallstricke
- Browser-Kompatibilität:
RTCIceTransport.getSelectedCandidatePair()und das Ereignisselectedcandidatepairchangegibt es in Chromium-Browsern und Safari. Firefox stelltRTCDtlsTransport.iceTransportbislang nicht (vollständig) bereit. Für browserübergreifenden Code sollten Sie deshalb aufgetStats()mit den Einträgen"candidate-pair"zurückgreifen. - Zeitpunkt: Vor dem Verbindungsaufbau ist
sender.transportoft nochnullundgetSelectedCandidatePair()liefertnull. Fragen Sie das Paar erst ab, wenn der Verbindungszustandconnectederreicht ist, oder hören Sie auf das Wechsel-Ereignis. - Datenschutz:
addresskann wegen mDNS-Verschleierung alsxxxx.localerscheinen oder leer sein. Echte IP-Adressen sind personenbezogene Daten und sollten nicht ungefragt an Analyse-Server geschickt werden. - Kein Konstruktor: Es handelt sich um ein Dictionary und nicht um eine Klasse.
new RTCIceCandidatePair()gibt es nicht. Wenn Sie ein solches Objekt selbst anlegen, übernimmt der Browser es nicht als aktiven Pfad.