JavaScript WebSocket API
Die JavaScript WebSocket API: Verbindungslebenszyklus, readyState, Text, JSON und Binärdaten senden, Reconnection und Sicherheit – mit Echo-Chat-Beispiel.
Einführung in die WebSocket-Technologie
WebSocket ist ein Protokoll, das einen Full-Duplex-Kommunikationskanal (bidirektional) zwischen Browser und Server über eine einzige, langlebige TCP-Verbindung bereitstellt. Sobald die Verbindung geöffnet ist, kann jede Seite jederzeit eine Nachricht senden, ohne auf die andere warten zu müssen — etwas, das einfaches HTTP nicht kann.
Diese Seite behandelt, was WebSockets lösen, den Verbindungslebenszyklus, das Senden von Text- und Binärdaten, die Arbeit mit JSON-Nachrichten, Reconnection, Sicherheit und wann eine Bibliothek statt der rohen API sinnvoller ist. Wir bauen alles anhand eines lauffähigen Echo-Chat-Beispiels auf.
Warum WebSockets statt HTTP?
Bei regulärem HTTP (einschließlich der Fetch API und XMLHttpRequest) muss der Client jeden Austausch initiieren. Um Live-Updates zu erhalten, muss man pollen — wiederholt fragen „gibt es etwas Neues?" — was Bandbreite verschwendet und Latenz erhöht. WebSockets kehren dies um: Der Server kann Daten pushen, sobald er etwas hat, mit nahezu keinem Overhead pro Nachricht.
| Ansatz | Richtung | Overhead | Am besten für |
|---|---|---|---|
| HTTP Request/Response | Client fragt, Server antwortet | Vollständige Header pro Anfrage | Einzelne Abfragen, REST APIs |
| Polling | Client fragt nach einem Timer | Viele verschwendete Anfragen | Einfache, seltene Updates |
| WebSocket | Beide pushen frei | Ein Handshake, kleine Frames | Chat, Live-Feeds, Spiele, Dashboards |
Verwenden Sie WebSockets, wenn der Server zuerst sprechen muss oder Nachrichten konstant fließen: Chat, Multiplayer-Spiele, kollaborative Editoren, Handelsticker und Live-Dashboards. Für gelegentliche unidirektionale Updates vom Server zum Client können Server-Sent Events oder die Push API einfacher sein.
Der WebSocket-Verbindungslebenszyklus
Sie öffnen eine Verbindung, indem Sie eine ws://-URL (unverschlüsselt) oder wss://-URL (verschlüsselt) an den WebSocket-Konstruktor übergeben. Die Verbindung durchläuft dann vier Zustände, die durch socket.readyState zugänglich sind:
| Konstante | Wert | Bedeutung |
|---|---|---|
WebSocket.CONNECTING | 0 | Handshake läuft (der Anfangszustand) |
WebSocket.OPEN | 1 | Bereit zum Senden und Empfangen |
WebSocket.CLOSING | 2 | Ein Schließen wurde angefordert |
WebSocket.CLOSED | 3 | Verbindung geschlossen oder Öffnen fehlgeschlagen |
Sie reagieren auf Zustandsübergänge mit vier Events: open, message, error und close. Die wichtigste Regel ist, dass socket.send() nur aufgerufen werden darf, wenn readyState OPEN ist — das Senden vor dem open-Event löst einen Fehler aus.
const socket = new WebSocket("wss://echo.websocket.events");
socket.addEventListener("open", () => {
console.log("open, readyState =", socket.readyState); // 1
socket.send("hello");
});
socket.addEventListener("message", (event) => {
console.log("received:", event.data); // "hello" (echoed back)
});
socket.addEventListener("close", (event) => {
console.log("closed, code =", event.code); // e.g. 1000
});Den WebSocket-Echo-Chat einrichten
Grundlegende HTML-Struktur
Zunächst erstellen wir die Benutzeroberfläche mit HTML, das einen Nachrichtenanzeigebereich, ein Eingabefeld und Steuerungsschaltflächen enthält.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>WebSocket Echo Chat</title>
</head>
<body>
<textarea id="chatBox" readonly style="width: 100%; height: 300px"></textarea><br />
<input type="text" id="messageInput" placeholder="Type a message..." style="width: 75%" />
<button onclick="sendMessage()">Send</button>
<button onclick="closeConnection()">Close Connection</button>
</body>
</html>WebSocket mit JavaScript integrieren
Das JavaScript zur Verwaltung der WebSocket-Kommunikation ist entscheidend für Echtzeit-Interaktionen.
<script>
// Accessing the chat box and message input elements from the HTML.
const chatBox = document.getElementById("chatBox");
const messageInput = document.getElementById("messageInput");
// Establishing a WebSocket connection to the echo server.
const socket = new WebSocket("wss://echo.websocket.events");
// When the connection is open, display a connected message in the chat box.
socket.addEventListener("open", function (event) {
chatBox.value += "Connected to the echo server\n";
});
// Handle incoming messages by adding them to the chat box.
socket.addEventListener("message", function (event) {
chatBox.value += "Echoed back: " + event.data + "\n";
});
// Handle connection errors.
socket.addEventListener("error", function (event) {
chatBox.value += "Connection error occurred.\n";
});
// Handle connection closure.
socket.addEventListener("close", function (event) {
chatBox.value += "Connection closed. Code: " + event.code + "\n";
});
// Function to send a message when the send button is clicked.
function sendMessage() {
const message = messageInput.value; // Get the message from the input field.
if (!message) return; // If there's no message, don't do anything.
socket.send(message); // Send the message to the server.
chatBox.value += "You: " + message + "\n"; // Show the message in the chat box.
messageInput.value = ""; // Clear the message input field.
}
// Function to close the WebSocket connection.
function closeConnection() {
if (socket.readyState === WebSocket.OPEN) {
socket.close(1000, "The user closed the connection"); // Close the connection normally.
chatBox.value += "Connection closed by user\n"; // Inform the user in the chat box.
} else {
alert("Connection is not open or already closed."); // Alert if the connection can't be closed.
}
}
// Ensure the WebSocket is closed properly when the webpage is closed or reloaded.
window.addEventListener("beforeunload", function () {
if (socket.readyState === WebSocket.OPEN) {
socket.close(1000, "The page is unloading"); // Close the connection normally.
}
});
</script>Dieses Skript richtet eine Chat-Funktion auf einer Webseite ein, die über WebSockets eine Verbindung zu einem Server herstellt. Hier eine kurze Erklärung seiner Bestandteile:
- Zugriff auf HTML-Elemente: Das Skript ruft das Chat-Feld und das Nachrichteneingabefeld von der Webseite ab, um mit ihnen zu interagieren.
- WebSocket-Verbindung: Es öffnet eine Verbindung zu einem Server, der Nachrichten zurückspiegelt. Das bedeutet, dass alles, was Sie an diesen Server senden, direkt zurückgesendet wird.
- Verbindungsstatus anzeigen: Wenn die Verbindung erfolgreich hergestellt wurde, wird im Chat-Feld eine Meldung angezeigt, dass die Verbindung zum Echo-Server hergestellt ist.
- Eingehende Nachrichten verarbeiten: Alle Nachrichten, die vom Server zurückkommen, werden dem Chat-Feld hinzugefügt und zeigen, dass der Server die Nachrichten gespiegelt hat.
- Nachrichten senden: Es gibt eine Funktion zum Senden von Nachrichten, die in das Eingabefeld eingegeben wurden. Wenn Text vorhanden ist, wird er an den Server gesendet und dann im Chat-Feld als Ihre Nachricht angezeigt.
- Verbindung schließen: Es gibt auch eine Funktion zum Schließen der WebSocket-Verbindung, wenn dies nötig ist — etwa wenn der Benutzer sie schließt oder die Webseite geschlossen wird.
Dieses Setup ermöglicht Echtzeit-Kommunikation mit dem Server und hilft dabei, zu testen und zu demonstrieren, wie Messaging-Anwendungen funktionieren.
Und jetzt setzen wir alles zusammen und sehen es in Aktion:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>WebSocket Echo Chat</title>
</head>
<body>
<textarea id="chatBox" readonly style="width: 100%; height: 300px">
</textarea>
<br />
<input
type="text"
id="messageInput"
placeholder="Type a message..."
style="width: 75%"
/>
<button onclick="sendMessage()">Send</button>
<button onclick="closeConnection()">Close Connection</button>
</body>
<script>
const chatBox = document.getElementById("chatBox");
const messageInput = document.getElementById("messageInput");
const socket = new WebSocket("wss://echo.websocket.events");
socket.addEventListener("open", function (event) {
chatBox.value += "Connected to the echo server\n";
});
socket.addEventListener("message", function (event) {
chatBox.value += "Echoed back: " + event.data + "\n";
});
socket.addEventListener("error", function (event) {
chatBox.value += "Connection error occurred.\n";
});
socket.addEventListener("close", function (event) {
chatBox.value += "Connection closed. Code: " + event.code + "\n";
});
function sendMessage() {
const message = messageInput.value;
if (!message) return;
socket.send(message);
chatBox.value += "You: " + message + "\n";
messageInput.value = "";
}
function closeConnection() {
if (socket.readyState === WebSocket.OPEN) {
socket.close(1000, "The user closed the connection");
chatBox.value += "Connection closed by user\n";
} else {
alert("Connection not open or already closed.");
}
}
window.addEventListener("beforeunload", function () {
if (socket.readyState === WebSocket.OPEN) {
socket.close(1000, "The page is unloading");
}
});
</script>
</html>Im obigen Beispiel können Sie, sobald Sie mit dem Server verbunden sind, Nachrichten senden und erhalten genau das zurück, was Sie eingegeben haben. Wenn Sie auf die Schaltfläche „Close Connection" klicken, wird die WebSocket-Verbindung beendet, und Sie erhalten keine gespiegelten Nachrichten mehr.
Erweiterte WebSocket-Funktionen und -Techniken
Strukturierte Daten als JSON senden
Echte Anwendungen senden selten einfache Strings — sie senden Objekte. Da das Übertragungsmedium nur Text oder Binärdaten transportiert, serialisieren Sie Objekte mit JSON.stringify() vor dem Senden und parsen sie auf der Empfängerseite mit JSON.parse(). Weitere Informationen zu diesem Format finden Sie unter Working with JSON.
// Sending an object
const payload = { type: "chat", user: "Ann", text: "Hi!" };
socket.send(JSON.stringify(payload));
// Receiving and parsing it
socket.addEventListener("message", (event) => {
const msg = JSON.parse(event.data);
console.log(msg.user + ": " + msg.text); // "Ann: Hi!"
});Ein gängiges Muster ist ein type-Feld, das es einer Verbindung ermöglicht, viele Arten von Nachrichten zu multiplexen — chat, presence, typing und so weiter — jede von ihrem eigenen Zweig verarbeitet.
Umgang mit Binärdaten
WebSockets sind nicht auf Text beschränkt. Sie können auch Binär-Frames übertragen, nützlich für Audio, Bilder oder Spielzustände. Setzen Sie socket.binaryType, um zu steuern, wie eingehende Binärdaten ankommen — "blob" (der Standard) oder "arraybuffer".
socket.binaryType = "arraybuffer";
// Send raw bytes
const bytes = new Uint8Array([72, 73]); // "HI"
socket.send(bytes);
socket.addEventListener("message", (event) => {
if (typeof event.data === "string") {
console.log("text frame:", event.data);
} else {
const view = new Uint8Array(event.data);
console.log("binary frame, length:", view.length);
}
});Automatische Wiederverbindung
Netzwerke brechen ab. Die rohe WebSocket-Implementierung verbindet sich nicht von selbst wieder — wenn close unerwartet ausgelöst wird, müssen Sie die Verbindung selbst neu aufbauen, idealerweise mit einem wachsenden (exponentiellen) Backoff, damit Sie den Server nicht überlasten.
let delay = 1000; // start at 1 second
function connect() {
const socket = new WebSocket("wss://echo.websocket.events");
socket.addEventListener("open", () => {
delay = 1000; // reset back-off after a successful connection
});
socket.addEventListener("close", () => {
setTimeout(connect, delay);
delay = Math.min(delay * 2, 30000); // cap at 30 seconds
});
}
connect();WebSocket-Sicherheit implementieren
Sicherheit ist beim Umgang mit WebSockets von größter Bedeutung:
- WSS verwenden: Verwenden Sie immer WebSocket Secure (WSS), das die zwischen Client und Server übertragenen Daten verschlüsselt.
- Authentifizierung: Implementieren Sie Token-basierte Authentifizierung, um sicherzustellen, dass nur autorisierte Benutzer WebSocket-Verbindungen herstellen können.
- Validierung: Validieren Sie alle an den Server gesendeten Daten ordnungsgemäß, um gängige Web-Schwachstellen wie XSS oder SQL Injection zu verhindern.
WebSocket und das Pub/Sub-Muster
Das Publish/Subscribe-Muster ist ein verbreitetes Modell in Echtzeit-Datendiensten, bei dem Nachrichten über einen Kanal übertragen werden. WebSocket-Dienste wie PubNub bieten APIs, die das Pub/Sub-Modell unterstützen, und erweitern damit die Möglichkeiten von WebSocket durch Verbindungsverwaltung, Datenverschlüsselung und kanalbasiertes Broadcasting.
WebSocket-Bibliotheken und Frameworks
Mehrere JavaScript-Bibliotheken erleichtern die Arbeit mit WebSockets und machen sie robuster:
- Socket.IO: Bietet zusätzliche Funktionen wie automatische Wiederverbindung, Event-Handling und Raumverwaltung.
- WebSocket-Node: Eine WebSocket-Server-Implementierung für Node.js.
- ReconnectingWebSocket: Eine kleine Bibliothek, die einfachen WebSockets Wiederverbindungsfunktionen hinzufügt.
Fazit
WebSocket-Technologie ist ein grundlegender Baustein für die Entwicklung interaktiver Echtzeit-Webanwendungen. Durch die Integration von WebSockets in Ihre Anwendungen ermöglichen Sie direkte, bidirektionale Interaktion zwischen Clients und Servern. Dieser Leitfaden behandelte den Verbindungslebenszyklus, das Echo-Chat-Beispiel, JSON- und Binärnachrichten, Wiederverbindung und Sicherheit — genug, um robuste Echtzeit-Funktionen zu entwickeln.
Siehe auch
- Fetch API — für einmalige HTTP-Anfragen, wenn kein Live-Kanal benötigt wird.
- XMLHttpRequest — die ältere Anfrage-API, auf der WebSockets und Fetch konzeptionell aufbauen.
- Push API — Server-zu-Client-Nachrichten auch wenn die Seite geschlossen ist.
- Working with JSON — das Standardformat für strukturierte WebSocket-Nachrichten.