Signatur
Beschreibung
Ein RTCIceCandidatePair beschreibt zwei ICE-Kandidaten: einen lokalen und einen entfernten (remote). Zusammen bilden sie den Netzwerkpfad, über den eine WebRTC-Verbindung Medien und Daten tatsächlich überträgt. Die Eigenschaft local enthält den RTCIceCandidate für die Seite dieses Rechners, also die lokale Adresse, den Port, das Protokoll und den Kandidatentyp.
Ein solches Paar bekommt man normalerweise über RTCIceTransport.getSelectedCandidatePair(). Den RTCIceTransport erreicht man über RTCRtpSender.transport.iceTransport oder RTCSctpTransport.transport.iceTransport (bei Datenkanälen). Wenn sich das gewählte Paar ändert, zum Beispiel nach einem ICE-Neustart oder Netzwerkwechsel, löst der Transport das Ereignis selectedcandidatepairchange aus.
Wichtige Einsatzfälle:
- Diagnose: herausfinden, ob die Verbindung direkt (
host), über NAT (srflx/prflx) oder über einen TURN-Server (relay) läuft. - Qualitätsüberwachung: Wird ein Relay genutzt, deutet das oft auf höhere Latenz und mehr Serverkosten hin.
- Protokollierung: Protokoll (
udp/tcp) und Netzwerktyp für das Monitoring festhalten.
Rückgabewert
type, protocol, address, port, candidate und relayProtocol.Beispiele
Lokalen Kandidaten des aktiven Pfads auslesen
// pc ist eine verbundene RTCPeerConnection
const logLocalCandidate = (pc) => {
const sender = pc.getSenders().find((s) => s.transport);
const iceTransport = sender?.transport?.iceTransport;
const pair = iceTransport?.getSelectedCandidatePair?.();
if (!pair) {
console.log('Kein ausgewähltes Kandidatenpaar verfügbar');
return;
}
const { type, protocol, address, port } = pair.local;
console.log(`Lokal: ${type} ${protocol} ${address}:${port}`);
};
pc.addEventListener('connectionstatechange', () => {
if (pc.connectionState === 'connected') logLocalCandidate(pc);
});
Auf Wechsel des Kandidatenpaars reagieren (TURN erkennen)
const watchCandidatePair = (iceTransport) => {
iceTransport.addEventListener('selectedcandidatepairchange', () => {
const { local, remote } = iceTransport.getSelectedCandidatePair();
const viaRelay = local.type === 'relay' || remote.type === 'relay';
console.log(viaRelay
? `Verbindung läuft über TURN (${local.relayProtocol ?? 'unbekannt'})`
: `Direkte Verbindung über ${local.protocol}`);
});
};
const [sender] = pc.getSenders();
if (sender?.transport) watchCandidatePair(sender.transport.iceTransport);
Fallback über getStats() für Browser ohne getSelectedCandidatePair()
const getLocalCandidateInfo = async (pc) => {
const stats = await pc.getStats();
let pairStats;
stats.forEach((report) => {
if (report.type === 'transport' && report.selectedCandidatePairId) {
pairStats = stats.get(report.selectedCandidatePairId);
}
});
// Firefox: das nominierte Paar direkt finden
if (!pairStats) {
stats.forEach((r) => {
if (r.type === 'candidate-pair' && r.nominated && r.state === 'succeeded') pairStats = r;
});
}
const local = pairStats && stats.get(pairStats.localCandidateId);
return local ? { type: local.candidateType, protocol: local.protocol, address: local.address } : null;
};
console.log(await getLocalCandidateInfo(pc));
// Wichtig · Fallstricke
- Kompatibilität:
RTCIceTransport.getSelectedCandidatePair()gibt es in Chromium-Browsern und im aktuellen Safari. Firefox bietet sie nicht zuverlässig an. Für browserübergreifenden Code eignet sichRTCPeerConnection.getStats()mit den Berichtencandidate-pairundlocal-candidateals Ausweichlösung. - Vor dem Aufbau der Verbindung gibt
getSelectedCandidatePair()nullzurück. Greifen Sie erst abconnectionState === 'connected'oder im Ereignisselectedcandidatepairchangeauf.localzu. sender.transportist erst nachsetLocalDescription()/setRemoteDescription()gesetzt. Bei Bundling (Standardfall) teilen sich alle Sender denselben Transport.- Datenschutz: Wegen mDNS-Verschleierung kann
addressbeihost-Kandidaten ein*.local-Name statt einer echten IP-Adresse sein. Senden Sie lokale IP-Adressen nicht ungefiltert an Analysedienste, denn sie können personenbezogene Daten sein. - Das Objekt ist eine Momentaufnahme. Nach einem ICE-Neustart oder Netzwerkwechsel müssen Sie das Paar neu abfragen.