Start · Sprachen · JavaScript · Referenz · RTCPeerConnection.createDataChannel()

RTCPeerConnection.createDataChannel()

Methode

Erstellt einen neuen <code>RTCDataChannel</code>, der mit dem Remote-Peer verknüpft ist und über den beliebige Daten (Text, Binärdaten) übertragen werden können.

seit JavaScript Baseline: alle modernen Browser (Chrome 25+, Firef Kategorie: webapi

Signatur

RTCPeerConnection.prototype.createDataChannel(label, options)

Beschreibung

Mit createDataChannel() legst du auf einer RTCPeerConnection einen bidirektionalen Datenkanal an. Die Daten laufen über SCTP innerhalb der verschlüsselten DTLS-Verbindung direkt zwischen den Peers, also ohne Umweg über einen Server. Typische Einsatzgebiete sind Chats, Dateiübertragung, Spielzustände in Multiplayer-Spielen oder die Synchronisation in Echtzeit-Anwendungen.

Wird der erste Datenkanal auf einer Verbindung angelegt, löst das ein negotiationneeded-Ereignis aus. Das Angebot (Offer) muss also nach dem Anlegen des Kanals erzeugt werden, damit die SDP einen m=application-Abschnitt enthält. Weitere Kanäle nutzen dieselbe SCTP-Verbindung und brauchen keine neue Aushandlung.

Standardmäßig wird der Kanal in-band ausgehandelt: Die Gegenseite erhält ein datachannel-Ereignis mit dem neuen Kanal. Alternativ kannst du mit negotiated: true und einer festen id auf beiden Seiten denselben Kanal out-of-band anlegen, dann wird kein datachannel-Ereignis ausgelöst.

Über die Optionen legst du fest, ob der Kanal zuverlässig und in Reihenfolge überträgt (wie TCP, Standard) oder unzuverlässig und ungeordnet (eher wie UDP). Die unzuverlässige Variante eignet sich für zeitkritische Daten wie Positionsupdates, bei denen veraltete Pakete wertlos sind.

Parameter

Name Typ Default Beschreibung
$label Pflicht string Lesbarer Name des Kanals, höchstens 65.535 Byte (UTF-8). Er muss nicht eindeutig sein und ist auf der Gegenseite über channel.label lesbar.
$options object {} Konfigurationsobjekt (RTCDataChannelInit) mit folgenden Feldern:
  • ordered (boolean, Standard true): Nachrichten in Sendereihenfolge zustellen.
  • maxPacketLifeTime (number): Höchstdauer in Millisekunden, in der Neuübertragungen versucht werden.
  • maxRetransmits (number): Höchstzahl an Neuübertragungen. Darf nicht zusammen mit maxPacketLifeTime gesetzt werden.
  • protocol (string, Standard ""): Name eines Unterprotokolls, z. B. "json".
  • negotiated (boolean, Standard false): true bei Out-of-band-Aushandlung durch die Anwendung.
  • id (number, 0–65.534): feste Stream-ID, nötig bei negotiated: true.
  • priority (string): "very-low", "low" (Standard), "medium" oder "high". Wird nicht von allen Browsern unterstützt.

Rückgabewert

Typ
RTCDataChannel
Beschreibung
Ein neues RTCDataChannel-Objekt. Anfangs hat es den readyState "connecting". Senden ist erst nach dem open-Ereignis möglich.

Beispiele

Datenkanal anlegen und Chat-Nachrichten senden (anrufende Seite)

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

// Kanal VOR createOffer() anlegen, damit er in der SDP landet
const chat = pc.createDataChannel('chat');

chat.addEventListener('open', () => {
  console.log('Kanal offen:', chat.label);
  chat.send(JSON.stringify({ text: 'Hallo!' }));
});

chat.addEventListener('message', (event) => {
  console.log('Empfangen:', event.data);
});

const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
// offer über den eigenen Signalisierungsserver an die Gegenseite schicken
signaling.send({ sdp: pc.localDescription });
Kanal offen: chat

Kanal auf der Gegenseite über das datachannel-Ereignis empfangen

const pc = new RTCPeerConnection();

pc.addEventListener('datachannel', (event) => {
  const channel = event.channel;
  console.log(`Neuer Kanal: ${channel.label}`);

  channel.onmessage = ({ data }) => {
    const msg = JSON.parse(data);
    console.log('Nachricht:', msg.text);
    channel.send(JSON.stringify({ text: 'Hallo zurück!' }));
  };
});
Neuer Kanal: chat Nachricht: Hallo!

Unzuverlässiger Kanal für Spielpositionen

// Ungeordnet, keine Neuübertragung: veraltete Positionen sind wertlos
const positions = pc.createDataChannel('positions', {
  ordered: false,
  maxRetransmits: 0
});

positions.binaryType = 'arraybuffer';

positions.onopen = () => {
  setInterval(() => {
    const buf = new Float32Array([player.x, player.y]);
    positions.send(buf.buffer);
  }, 50);
};

Out-of-band ausgehandelter Kanal mit fester ID

// Auf BEIDEN Peers identisch aufrufen – kein datachannel-Ereignis
const control = pc.createDataChannel('control', {
  negotiated: true,
  id: 0
});

control.onopen = () => console.log('Steuerkanal bereit, id =', control.id);
Steuerkanal bereit, id = 0

// Wichtig · Fallstricke

  • Reihenfolge beachten: Legst du den ersten Kanal erst nach createOffer() an, fehlt er in der SDP und es ist eine neue Aushandlung nötig. Am besten reagierst du auf negotiationneeded.
  • Senden vor open wirft einen InvalidStateError. Immer auf das open-Ereignis warten oder readyState === 'open' prüfen.
  • maxPacketLifeTime und maxRetransmits gleichzeitig zu setzen, führt zu einem TypeError. Ein label oder protocol über 65.535 Byte ebenfalls.
  • Ist die Verbindung geschlossen (signalingState === 'closed'), wirft die Methode einen InvalidStateError. Eine bereits vergebene id führt zu einem OperationError.
  • Nachrichtengröße: Die zuverlässig übertragbare Größe hängt vom Browser ab, siehe pc.sctp.maxMessageSize. Große Dateien in Blöcke von ca. 16–64 KiB aufteilen und über bufferedAmount bzw. bufferedamountlow den Datenfluss steuern.
  • Die Übertragung ist über DTLS verschlüsselt. Die Signalisierung (Austausch von SDP und ICE-Kandidaten) musst du aber selbst absichern, z. B. über WSS. Empfangene Daten sind nicht vertrauenswürdig: Nicht ungeprüft per innerHTML einfügen (XSS).
  • Die Option priority wird nicht überall unterstützt. Ältere Optionen wie maxRetransmitTime sind veraltet.