Signatur
Beschreibung
Ein RTCIceCandidate beschreibt einen einzelnen ICE-Kandidaten (Interactive Connectivity Establishment). Das ist eine mögliche Verbindungsadresse, über die zwei WebRTC-Gegenstellen Daten austauschen können. Dazu gehören lokale Host-Adressen, per STUN ermittelte öffentliche Adressen (srflx) und TURN-Relay-Adressen (relay). Der Browser sammelt diese Kandidaten selbstständig, sobald eine RTCPeerConnection eine lokale Beschreibung erhalten hat, und meldet sie über das Ereignis icecandidate.
Typischer Ablauf: Du empfängst im icecandidate-Handler ein RTCIceCandidate-Objekt, wandelst es mit toJSON() in ein serialisierbares Objekt um und schickst es über deinen Signalisierungskanal (z. B. WebSocket) an die Gegenstelle. Dort übergibst du es an RTCPeerConnection.addIceCandidate(). Dieses Verfahren heißt Trickle ICE: Die Kandidaten werden einzeln verschickt, sobald sie gefunden werden, und nicht erst gesammelt.
Die wichtigsten schreibgeschützten Eigenschaften sind candidate (die SDP-Zeile mit dem Kandidaten), sdpMid, sdpMLineIndex und usernameFragment. Außerdem gibt es die aus der Kandidatenzeile ausgelesenen Felder foundation, component, priority, address, protocol, port, type, tcpType, relatedAddress und relatedPort.
Den Konstruktor brauchst du selten. addIceCandidate() nimmt auch direkt ein einfaches Objekt (RTCIceCandidateInit) entgegen. Nützlich ist new RTCIceCandidate() vor allem, wenn du empfangene Kandidaten vorab auswerten oder filtern willst.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $candidateInfo | RTCIceCandidateInit | {} | Objekt für den Konstruktor new RTCIceCandidate(candidateInfo) mit den Feldern candidate (string, SDP-Zeile a=candidate:… ohne das Präfix a=), sdpMid (string|null), sdpMLineIndex (number|null) und usernameFragment (string|null). Mindestens sdpMid oder sdpMLineIndex muss gesetzt sein, sonst wird ein TypeError ausgelöst. |
Rückgabewert
RTCIceCandidate-Objekt. Die Eigenschaften wie address, port oder type werden aus dem Kandidaten-String ausgelesen und sind schreibgeschützt.Beispiele
Kandidaten sammeln und per WebSocket versenden (Trickle ICE)
const ws = new WebSocket('wss://signal.example.com');
const pc = new RTCPeerConnection({
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
});
pc.addEventListener('icecandidate', ({ candidate }) => {
if (candidate) {
// RTCIceCandidate in serialisierbares Objekt umwandeln
ws.send(JSON.stringify({ type: 'candidate', candidate: candidate.toJSON() }));
} else {
// null bedeutet: Sammeln abgeschlossen
ws.send(JSON.stringify({ type: 'end-of-candidates' }));
}
});
pc.createDataChannel('chat');
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
Empfangene Kandidaten der Gegenstelle hinzufügen
ws.addEventListener('message', async (event) => {
const msg = JSON.parse(event.data);
if (msg.type === 'candidate') {
try {
await pc.addIceCandidate(new RTCIceCandidate(msg.candidate));
} catch (err) {
console.error('Kandidat abgelehnt:', err);
}
} else if (msg.type === 'end-of-candidates') {
await pc.addIceCandidate(); // signalisiert das Ende der Kandidaten
}
});
Kandidaten mit dem Konstruktor erzeugen und auswerten
const cand = new RTCIceCandidate({
candidate: 'candidate:842163049 1 udp 1677729535 203.0.113.7 54321 typ srflx raddr 192.168.1.20 rport 54321 generation 0',
sdpMid: '0',
sdpMLineIndex: 0
});
console.log(cand.type, cand.protocol, cand.address, cand.port);
console.log(cand.relatedAddress);
console.log(JSON.stringify(cand.toJSON()));
Nur TURN-Relay-Kandidaten durchlassen
pc.addEventListener('icecandidate', ({ candidate }) => {
if (!candidate) return;
if (candidate.type === 'relay') {
sendToPeer(candidate.toJSON());
} else {
console.log('Verworfen:', candidate.type, candidate.address);
}
});
function sendToPeer(data) {
ws.send(JSON.stringify({ type: 'candidate', candidate: data }));
}
// Wichtig · Fallstricke
- Das Ende-Signal: Im
icecandidate-Ereignis istevent.candidate === null, wenn das Sammeln beendet ist. Manche Browser liefern vorher zusätzlich einen Kandidaten mit leeremcandidate-String. Behandle beide Fälle und schicke sie nicht als normale Kandidaten weiter. - Reihenfolge beachten:
addIceCandidate()schlägt fehl (InvalidStateError), wenn noch keineremoteDescriptiongesetzt ist. Früh eintreffende Kandidaten solltest du zwischenspeichern und erst nachsetRemoteDescription()hinzufügen. - Serialisierung: Ein
RTCIceCandidatekannst du nicht direkt sinnvoll perpostMessageoder ohnetoJSON()verschicken. Übertrage immercandidate.toJSON().JSON.stringify()ruft diese Methode automatisch auf. - Datenschutz: Host-Kandidaten verraten lokale IP-Adressen. Moderne Browser verschleiern sie deshalb mit mDNS-Namen (
*.local), sodassaddresskeine echte IP enthalten muss. MiticeTransportPolicy: 'relay'erzwingst du reine TURN-Verbindungen. - Kompatibilität: In allen modernen Browsern verfügbar. Die ausgelesenen Felder (
address,typeusw.) unterstützt Firefox erst seit Version 68. Ältere Safari-Versionen könnenusernameFragmentalsnullliefern. Veralteter Code nutzt noch das PräfixwebkitRTCIceCandidateodermozRTCIceCandidate, das ist heute nicht mehr nötig. - Unter Node.js gibt es diese Schnittstelle nicht. Dort brauchst du Bibliotheken wie
wrtcoderwerift.