Start · Sprachen · JavaScript · Referenz · RTCDataChannel.send()

RTCDataChannel.send()

Methode

Sendet Daten (Text, Blob, ArrayBuffer oder TypedArray/DataView) über einen geöffneten <code>RTCDataChannel</code> direkt an den entfernten Peer.

seit JavaScript Baseline: alle modernen Browser (seit ca. 2020 wei Kategorie: webapi

Signatur

RTCDataChannel.prototype.send(data)

Beschreibung

Mit send() überträgt man beliebige Anwendungsdaten Peer-to-Peer über eine WebRTC-Verbindung, ohne dass ein Server die Nutzdaten weiterleitet. Typische Einsatzfälle sind Chats, Spielzustände, Steuerbefehle oder Dateiübertragungen zwischen Browsern.

Der Kanal muss sich im Zustand "open" befinden (channel.readyState === "open"). Ruft man send() in einem anderen Zustand auf, wird ein InvalidStateError ausgelöst. Deshalb sendet man am besten erst nach dem open-Event.

Die Methode arbeitet asynchron: Die Daten werden in einen internen Puffer gelegt, und bufferedAmount erhöht sich entsprechend. Ob die Übertragung zuverlässig und geordnet erfolgt, hängt von den Optionen ab, mit denen der Kanal über RTCPeerConnection.createDataChannel() erzeugt wurde (ordered, maxRetransmits, maxPacketLifeTime).

Beim Empfänger kommen die Daten über das message-Event an. Binärdaten werden dort je nach binaryType des empfangenden Kanals als ArrayBuffer (Standard) oder Blob geliefert.

Parameter

Name Typ Default Beschreibung
$data Pflicht string | Blob | ArrayBuffer | TypedArray | DataView Die zu sendenden Daten. Strings werden als UTF-8 übertragen, alle anderen Typen als Binärnachricht.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined). Fehler werden als Ausnahme geworfen, z. B. InvalidStateError, wenn der Kanal nicht offen ist, oder TypeError, wenn die Nachricht zu groß für die Verbindung ist bzw. der Puffer voll ist (je nach Browser OperationError).

Beispiele

Textnachricht nach dem Öffnen senden

const pc = new RTCPeerConnection();
const channel = pc.createDataChannel('chat');

channel.addEventListener('open', () => {
  channel.send('Hallo, Peer!');
  console.log('Nachricht gesendet, gepuffert:', channel.bufferedAmount);
});

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

// Signalisierung (Offer/Answer, ICE) hier weglassen – wird z. B. über WebSocket ausgetauscht
Nachricht gesendet, gepuffert: 12

JSON-Objekte strukturiert übertragen

const sendJSON = (channel, payload) => {
  if (channel.readyState !== 'open') {
    console.warn('Kanal nicht offen:', channel.readyState);
    return false;
  }
  channel.send(JSON.stringify(payload));
  return true;
};

// Empfangsseite
const handleMessage = (event) => {
  const { type, x, y } = JSON.parse(event.data);
  console.log(`${type} bei ${x}/${y}`);
};

// Nutzung: sendJSON(channel, { type: 'move', x: 10, y: 20 });
move bei 10/20

Datei in Blöcken mit Backpressure senden

const CHUNK_SIZE = 16 * 1024; // 16 KiB: sicher über alle Browser hinweg

const sendFile = async (channel, file) => {
  channel.bufferedAmountLowThreshold = 1024 * 1024; // 1 MiB
  const buffer = await file.arrayBuffer();

  for (let offset = 0; offset < buffer.byteLength; offset += CHUNK_SIZE) {
    // Warten, wenn der interne Puffer zu voll wird
    if (channel.bufferedAmount > channel.bufferedAmountLowThreshold) {
      await new Promise((resolve) =>
        channel.addEventListener('bufferedamountlow', resolve, { once: true })
      );
    }
    channel.send(buffer.slice(offset, offset + CHUNK_SIZE));
  }
  channel.send(JSON.stringify({ done: true, name: file.name }));
  console.log(`${file.name} gesendet (${buffer.byteLength} Bytes)`);
};
bild.png gesendet (245760 Bytes)

// Wichtig · Fallstricke

  • Zustand prüfen: Vor dem open-Event oder nach dem Schließen wirft send() einen InvalidStateError. Immer readyState prüfen oder im open-Handler senden.
  • Nachrichtengröße: Die maximale Größe hängt von der Aushandlung ab (RTCPeerConnection.sctp.maxMessageSize). Für Kompatibilität zwischen Browsern große Daten in Blöcke von etwa 16 KiB aufteilen; zu große Nachrichten lösen einen TypeError aus.
  • Backpressure: Wird schneller gesendet als übertragen, wächst bufferedAmount. Läuft der interne Puffer über, schließen manche Browser den Kanal. Mit bufferedAmountLowThreshold und dem Event bufferedamountlow drosseln.
  • Blob-Unterstützung: Das Senden von Blob wurde in Chromium lange nicht unterstützt. Für maximale Kompatibilität besser ArrayBuffer verwenden (await blob.arrayBuffer()).
  • Zuverlässigkeit: Bei Kanälen mit maxRetransmits oder maxPacketLifeTime können Nachrichten verloren gehen oder in anderer Reihenfolge ankommen.
  • Sicherheit: Die Übertragung ist per DTLS verschlüsselt. Empfangene Daten stammen aber von einem fremden Peer und müssen geprüft werden. Nie ungeprüft in innerHTML einsetzen oder ausführen.