Start · Sprachen · JavaScript · Referenz · WebSocket

WebSocket

Schnittstelle

Stellt eine dauerhafte, bidirektionale Verbindung zu einem Server über das WebSocket-Protokoll her und sendet bzw. empfängt darüber Text- und Binärdaten.

seit JavaScript Baseline: alle Browser (seit 2012); Node.js 22+ gl Kategorie: webapi

Signatur

interface WebSocket extends EventTarget

Beschreibung

Die Schnittstelle WebSocket öffnet eine Vollduplex-Verbindung zwischen Browser und Server. Anders als bei fetch() bleibt die Verbindung nach dem Handshake offen. Beide Seiten können jederzeit Nachrichten senden, ohne dass jedes Mal eine neue HTTP-Anfrage nötig ist. Typische Anwendungen sind Chats, Live-Dashboards, Mehrspieler-Spiele, Börsenkurse oder kollaboratives Bearbeiten.

Eine Verbindung entsteht mit new WebSocket(url, protocols). Der Aufbau läuft asynchron: Erst wenn das Ereignis open ausgelöst wurde, ist readyState gleich WebSocket.OPEN und send() kann genutzt werden. Eingehende Daten kommen über das Ereignis message an. Fehler meldet error, das Ende der Verbindung meldet close (mit code, reason und wasClean).

Wichtige Mitglieder:

  • Methoden: send(data) sendet einen String, ein Blob, einen ArrayBuffer oder eine ArrayBufferView. close(code, reason) beendet die Verbindung sauber.
  • Eigenschaften: readyState (0 = CONNECTING, 1 = OPEN, 2 = CLOSING, 3 = CLOSED), bufferedAmount, binaryType ("blob" oder "arraybuffer"), protocol, extensions und url.
  • Ereignisse: open, message, error und close. Sie lassen sich per addEventListener() oder über onopen, onmessage, onerror und onclose abonnieren.

Das Protokoll selbst hat keine automatische Wiederverbindung, keine Bestätigungen und keine Gegendruck-Steuerung (Backpressure). Solche Funktionen muss die Anwendung selbst bauen, etwa eine Wiederverbindung mit exponentiellem Backoff oder Heartbeats.

Parameter

Name Typ Default Beschreibung
$url Pflicht string | URL Adresse des WebSocket-Servers mit dem Schema ws: oder wss:. Neuere Browser akzeptieren auch http:/https: und relative URLs und wandeln sie passend um.
$protocols string | string[] [] Ein oder mehrere Unterprotokolle (z. B. "graphql-ws"). Der Server wählt eines aus, das danach in ws.protocol steht.

Rückgabewert

Typ
WebSocket
Beschreibung
Eine neue WebSocket-Instanz im Zustand CONNECTING. Bei einer ungültigen URL wirft der Konstruktor sofort einen SyntaxError (DOMException).

Beispiele

Verbindung öffnen, senden und empfangen

const ws = new WebSocket('wss://echo.websocket.org');

ws.addEventListener('open', () => {
  console.log('Verbunden, readyState =', ws.readyState);
  ws.send(JSON.stringify({ type: 'hallo', text: 'Servus Server!' }));
});

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

ws.addEventListener('error', () => {
  console.error('WebSocket-Fehler');
});

ws.addEventListener('close', (event) => {
  console.log(`Geschlossen: code=${event.code}, sauber=${event.wasClean}`);
});
Verbunden, readyState = 1 Empfangen: {"type":"hallo","text":"Servus Server!"}

Binärdaten mit ArrayBuffer austauschen

const ws = new WebSocket('wss://echo.websocket.org');
ws.binaryType = 'arraybuffer'; // statt Standard 'blob'

ws.onopen = () => {
  const bytes = new Uint8Array([1, 2, 3, 250]);
  ws.send(bytes);
};

ws.onmessage = ({ data }) => {
  if (data instanceof ArrayBuffer) {
    console.log('Bytes:', Array.from(new Uint8Array(data)));
    ws.close(1000, 'Fertig');
  }
};
Bytes: [1, 2, 3, 250]

Automatische Wiederverbindung mit exponentiellem Backoff

const connect = (url, onMessage, attempt = 0) => {
  const ws = new WebSocket(url);

  ws.onopen = () => {
    console.log('Verbunden');
    attempt = 0; // Zähler nach Erfolg zurücksetzen
  };
  ws.onmessage = (e) => onMessage(e.data);
  ws.onclose = (e) => {
    if (e.code === 1000) return; // absichtlich geschlossen
    const delay = Math.min(30000, 1000 * 2 ** attempt);
    console.log(`Neuer Versuch in ${delay} ms`);
    setTimeout(() => connect(url, onMessage, attempt + 1), delay);
  };
  return ws;
};

connect('wss://example.com/live', (data) => console.log('Update:', data));
Verbunden Update: ...

Nur senden, wenn offen – mit Gegendruck-Prüfung

const safeSend = (ws, payload) => {
  if (ws.readyState !== WebSocket.OPEN) {
    console.warn('Nicht verbunden, Nachricht verworfen');
    return false;
  }
  // Puffer zu voll? Dann lieber warten
  if (ws.bufferedAmount > 1_000_000) {
    console.warn('Sendepuffer voll:', ws.bufferedAmount, 'Bytes');
    return false;
  }
  ws.send(typeof payload === 'string' ? payload : JSON.stringify(payload));
  return true;
};

const ws = new WebSocket('wss://echo.websocket.org');
console.log(safeSend(ws, { ping: Date.now() }));
Nicht verbunden, Nachricht verworfen false

// Wichtig · Fallstricke

  • send() vor open: Ein Aufruf im Zustand CONNECTING wirft einen InvalidStateError. Nach dem Schließen verwirft der Browser die Daten stillschweigend. Prüfe deshalb vorher immer readyState.
  • Fehlerdetails: Das Ereignis error enthält aus Sicherheitsgründen keine Ursache. Hinweise liefert nur der code im folgenden close-Ereignis, z. B. 1006 für einen abnormalen Abbruch.
  • close(code): Erlaubt sind nur 1000 oder Werte von 3000 bis 4999. Andere Werte werfen einen InvalidAccessError. Der reason darf höchstens 123 Byte (UTF-8) lang sein.
  • Sicherheit: Nutze in Produktion immer wss://, denn auf HTTPS-Seiten blockiert der Browser ws:// als Mixed Content. WebSockets unterliegen nicht der Same-Origin-Policy und nicht CORS. Der Server muss deshalb den Header Origin selbst prüfen, sonst droht Cross-Site WebSocket Hijacking. Eigene Header wie Authorization lassen sich nicht setzen. Zur Anmeldung dienen Cookies, ein Token in der ersten Nachricht oder ein kurzlebiges Token in der URL (Vorsicht: URLs landen in Logs). Empfangene Daten sind nicht vertrauenswürdig: kein innerHTML mit Serverdaten, JSON.parse in try/catch kapseln.
  • Gegendruck: send() blockiert nie. Bei großen Datenmengen wächst bufferedAmount ohne Grenze. Neuere Alternativen mit Gegendruck-Steuerung sind WebSocketStream (experimentell, nur Chromium) und WebTransport.
  • Verbindungsabbrüche: Proxys und mobile Netze trennen inaktive Verbindungen oft stillschweigend. Regelmäßige Ping-Nachrichten auf Anwendungsebene helfen, denn die Browser-API gibt keinen Zugriff auf Ping-/Pong-Frames.
  • Kompatibilität: Wird in allen modernen Browsern unterstützt. In Node.js ist WebSocket ab Version 22 global als Client verfügbar, davor braucht man z. B. das Paket ws. Einen Server bietet die Browser-API nicht.