Zruck zum Blog, du Zniachtl
Mai 2026·3 Min. zum LesnVo da KI gmocht

A sanfte Einführung in WebSockets

#websockets#networking#javascript

HTTP is Request-Response: Da Client frogt, da Server antwortet, und die Verbindung hot ihre Schuldigkeit tan. Des Modell bricht zam, sobois da Server dem Client wos sogn muass, ohne vorher gfrogt worn zum sei - a Chatnachricht kummt o, a Aktienkurs tickt, a Build wird fertig. WebSockets gibt's genau dafür: a einzige langlebige Verbindung, wo jede Seitn jederzeit der ondern a Nachricht schicken kann, ohne den Per-Request-Overhead von HTTP.

Warum ned einfach pollen?

Vor den WebSockets woar der Standard-Workaround Polling: Da Client frogt olle poar Sekunden "gibt's wos Neis?".

setInterval(async () => {
  const response = await fetch('/api/messages/latest');
  const messages = await response.json();
  renderNewMessages(messages);
}, 3000);

Des funktioniert, is aber a schlechter Deal in beide Richtungen. Pollst du zu langsam, fühlen si Updates zäh an; pollst du zu schnö, mochst du meistens verschwendete HTTP-Requests - jeder mit eigenem TCP-Handshake-Overhead (oder Komplexität vo da Verbindungswiederverwendung), Headern und serverseitiger Request-Behandlung -, nur um normalerweise "nix hot si gändert" zum hörn. A WebSocket-Verbindung wird einmal aufgmacht und schickt dann einfach de eigentlichen Daten, in jede Richtung, in dem Moment, wo's de gibt.

Da Handshake: no immer HTTP, nur kurz

A WebSocket-Verbindung startet ois normaler HTTP-Request mit am Upgrade-Header. Da Server stimmt zu, des Protokoll zum wechsln, und ab dem Punkt trägt dieselbe TCP-Verbindung s'WebSocket-Framing statt HTTP.

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

Du baust des nie von Hand - die WebSocket-API vom Browser und serverseitige Bibliotheken erledigen den Handshake. Es zahlt si aber, zu wissn, dass's des gibt: Deswegn nutzt a WebSocket-URL ws:// oda wss:// (die sichere Version über TLS) statt http://, und deswegn kann a WebSocket-Verbindung von denselben Sochn blockiert wern wia a HTTP-Request - CORS-ähnliche Origin-Checks, Proxys ohne Upgrade-Support, Firmen-Firewalls.

Die Client-Seitn

const socket = new WebSocket('wss://example.com/chat');

socket.addEventListener('open', () => {
  console.log('connected');
  socket.send(JSON.stringify({ type: 'join', room: 'general' }));
});

socket.addEventListener('message', (event) => {
  const data = JSON.parse(event.data);
  console.log('received:', data);
});

socket.addEventListener('close', (event) => {
  console.log(`connection closed: ${event.code} ${event.reason}`);
});

socket.addEventListener('error', (event) => {
  console.error('socket error', event);
});

Vier Events decken den ganzen Lebenszyklus ab: open, sobois da Handshake fertig is, message für jeden eingehenden Frame, close, wenn die Verbindung endet (von jeder Seitn), und error für Fehler auf Transportebene. Olles, wos du schickst und empfängst, is Text oda Binär - es gibt ka eingbautes Request/Response-Pairing, wennst also a Antwort an a bestimmte gsendete Nachricht koppeln wüst, liegt des an deim Anwendungsprotokoll (typischerweise: a ID in die Payload einepacken).

A minimaler Server, mit Nodes ws-Bibliothek

import { WebSocketServer } from 'ws';

const wss = new WebSocketServer({ port: 8080 });
const clients = new Set();

wss.on('connection', (socket) => {
  clients.add(socket);
  console.log(`client connected, ${clients.size} total`);

  socket.on('message', (raw) => {
    const message = JSON.parse(raw.toString());
    // broadcast to everyone except the sender
    for (const client of clients) {
      if (client !== socket && client.readyState === client.OPEN) {
        client.send(JSON.stringify(message));
      }
    }
  });

  socket.on('close', () => {
    clients.delete(socket);
    console.log(`client disconnected, ${clients.size} remaining`);
  });
});

Des is a kompletter Broadcast-Chat-Server: Jeder verbundene Client kriagt jede Nachricht weitergeleitet, de wer ondrer gschickt hot. Das Set an offenen Sockets is die gesamte Vorstellung vom Server, "wer zuhört" - ka Polling, ka Timestamp-Vergleich, einfach Push.

Wiederverbinden is dei Job, ned der vom Browser

Wenn die Verbindung obreißt - Server-Neustart, Netzwerk-Wackler, Laptop geht schlofn -, verbindet si des WebSocket-Objekt ned söba neu. Do muasst dich explizit drum kümmern, meistens mit exponentiellem Backoff, damit a Serverausfall ned von jedem Client im Gleichschritt bombardiert wird, sobois er wieder do is.

function connectWithRetry(url, { onMessage }) {
  let attempt = 0;

  function connect() {
    const socket = new WebSocket(url);

    socket.addEventListener('open', () => {
      attempt = 0; // reset backoff once we're actually connected
    });

    socket.addEventListener('message', onMessage);

    socket.addEventListener('close', () => {
      const delay = Math.min(1000 * 2 ** attempt, 30000);
      attempt++;
      setTimeout(connect, delay);
    });
  }

  connect();
}

Die Delays verdoppeln si bei jedem Versuch (1s, 2s, 4s, 8s...) bis zu ana Obergrenze von 30 Sekunden und setzn si auf null zruck, sobois a Verbindung tatsächlich klappt. Produktivsysteme fügn meist zufälligen Jitter dazu, damit viele Clients, de nach demselben Ausfall wiederverbinden, ned olle zu exakt denselben Zeitpunkten nochamoi probiern.

Wann WebSockets des falsche Werkzeug sand

Sie sand ka universelles Upgrade gegenüber HTTP. Wenn da Client nur gelegentlich vom Server ausgehende Updates braucht und a poar Sekunden Latenz verträgt, sand Server-Sent Events (SSE) einfacher - einseitig (nur Server zum Client), automatisches Wiederverbinden eingbaut, und einfach a normale HTTP-Antwort, de da Browser offen zum halten woaß. Wenn die Kommunikation wirklich nur Request-Response is, is normales HTTP mit fetch noch einfacher und gibt dir Caching, Retries und Standard-HTTP-Semantik gratis dazu. Greif gezielt zu am WebSocket, wennst latenzarme, bidirektionale Kommunikation brauchst - Chat, Multiplayer-State, kollaboratives Editieren, Live-Dashboards, wo da Server so oft pusht, wie da Client frogt.

NeicherRetry-Strategien: Exponential Backoff und JitterElterAsync Iteratoren und Generatoren in JavaScript