Start · Sprachen · JavaScript · Referenz · RTCPeerConnectionIceEvent.candidate

RTCPeerConnectionIceEvent.candidate

Eigenschaft

Schreibgeschützte Eigenschaft, die den <code>RTCIceCandidate</code> eines <code>icecandidate</code>-Ereignisses liefert, oder <code>null</code>, wenn die Kandidatensuche beendet ist.

seit JavaScript Baseline: alle modernen Browser (seit ca. 2017) Kategorie: webapi

Signatur

RTCPeerConnectionIceEvent.candidate

Beschreibung

Die Eigenschaft candidate eines RTCPeerConnectionIceEvent enthält den ICE-Kandidaten, den die lokale RTCPeerConnection gerade gefunden hat. Ein ICE-Kandidat beschreibt einen möglichen Netzwerkweg (Host-Adresse, über STUN ermittelte öffentliche Adresse oder TURN-Relay), über den der entfernte Partner die Verbindung aufbauen kann.

Man wertet die Eigenschaft fast immer im Handler des Ereignisses icecandidate aus. Jeder gefundene Kandidat muss über den eigenen Signalisierungskanal (z. B. WebSocket) an die Gegenseite geschickt werden. Dort wird er mit RTCPeerConnection.addIceCandidate() hinzugefügt. Dieses Vorgehen heißt Trickle ICE: Kandidaten werden verschickt, sobald sie gefunden sind, und nicht erst nach Abschluss der Suche.

Ist candidate gleich null, hat der Browser die Kandidatensuche (ICE Gathering) abgeschlossen. Dieses Signal kann man an die Gegenseite weitergeben, damit sie ebenfalls weiß, dass keine Kandidaten mehr kommen. Außerdem gibt es in manchen Implementierungen am Ende einer Generation einen Kandidaten mit leerem candidate-String. Er bedeutet „Ende der Kandidaten“ für diese Generation und sollte wie ein normaler Kandidat weitergeleitet werden.

Rückgabewert

Typ
RTCIceCandidate | null
Beschreibung
Das RTCIceCandidate-Objekt mit dem gefundenen Kandidaten oder null, wenn die Kandidatensuche abgeschlossen ist.

Beispiele

Kandidaten per WebSocket an die Gegenseite senden (addEventListener)

const signaling = new WebSocket('wss://signal.example.com');
const pc = new RTCPeerConnection({
  iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
});

pc.addEventListener('icecandidate', (event) => {
  if (event.candidate) {
    // toJSON() liefert candidate, sdpMid, sdpMLineIndex, usernameFragment
    signaling.send(JSON.stringify({ type: 'candidate', candidate: event.candidate.toJSON() }));
  } else {
    // null: Kandidatensuche beendet
    signaling.send(JSON.stringify({ type: 'end-of-candidates' }));
  }
});

pc.createDataChannel('chat');
const offer = await pc.createOffer();
await pc.setLocalDescription(offer); // startet die Kandidatensuche

Kandidaten auf der Gegenseite hinzufügen

signaling.addEventListener('message', async ({ data }) => {
  const msg = JSON.parse(data);
  if (msg.type === 'candidate') {
    try {
      await pc.addIceCandidate(msg.candidate);
    } catch (err) {
      console.error('Kandidat abgelehnt:', err);
    }
  } else if (msg.type === 'end-of-candidates') {
    // Ohne Argument signalisiert addIceCandidate das Ende
    await pc.addIceCandidate();
  }
});

Kandidatentypen protokollieren (onicecandidate-Property)

const pc = new RTCPeerConnection({
  iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
});

pc.onicecandidate = ({ candidate }) => {
  if (!candidate) {
    console.log('Suche abgeschlossen');
    return;
  }
  console.log(candidate.type, candidate.protocol, candidate.address, candidate.port);
};

pc.createDataChannel('test');
await pc.setLocalDescription(await pc.createOffer());
host udp 3f1c9a2e-....local 54321 srflx udp 203.0.113.17 54321 Suche abgeschlossen

// Wichtig · Fallstricke

  • Immer auf null prüfen: Das letzte icecandidate-Ereignis liefert candidate === null. Wer ohne Prüfung event.candidate.toJSON() aufruft, bekommt einen TypeError.
  • Beim Versand über JSON lieber candidate.toJSON() verwenden (oder JSON.stringify direkt), damit sdpMid und sdpMLineIndex erhalten bleiben. Nur den candidate-String zu schicken reicht nicht.
  • Kandidaten, die auf der Gegenseite ankommen, bevor setRemoteDescription() aufgerufen wurde, lösen bei addIceCandidate() einen Fehler aus. Solche Kandidaten sollte man puffern und erst danach hinzufügen.
  • Datenschutz: Kandidaten können lokale und öffentliche IP-Adressen verraten. Moderne Browser verschleiern Host-Adressen deshalb mit mDNS-Namen (*.local). Die Eigenschaft address ist also nicht immer eine echte IP.
  • Die Eigenschaft ist schreibgeschützt. Eigene Ereignisse lassen sich mit new RTCPeerConnectionIceEvent('icecandidate', { candidate }) erzeugen.
  • Wird in allen aktuellen Browsern unterstützt. Ältere Implementierungen (vor 2018) lösten das Ende der Suche teils nur über icegatheringstatechange aus.