Da bald die Abgabe meiner Abschlussarbeit ansteht und mein Thema sich rund um Websockets dreht, wird es Zeit eine Einführung in das relativ neue Themengebiet zu schreiben. Das WebSocket-Protokoll ist ein auf TCP basierendes Netzwerkprotokoll, das entworfen wurde, um eine bidirektionale Verbindung zwischen einer Webanwendung und einem WebSocket-Server bzw. einem Web-Server, der WebSockets unterstützt, herzustellen.
Das Problem: Client-Server und Server-Client Verbindungen mit geringer Latenz
Das HTTP-Protokoll basiert mehr oder weniger auf dem Anfrage/Antwort Prinzip. Der Client lädt eine Seite und es passiert weiter nichts, bis er auf einen weiteren Link klickt. Gegen 2005 sorgte dann AJAX dafür, dass das Internet dynamischer wirkte. Dennoch wurde die gesamte HTTP-Kommunikation vom Client gesteuert. Dieser benötigt zum Ldaen neuer Daten vom Server die Interaktion der Nutzer oder periodische Abfragen.
Beim WebSocket-Protokoll werden keine Aktionen der Nutzer benötigt, hier reicht es im Client eine Verbindung zu öffnen. Diese geöffnete Verbindung kann dann aktiv vom Server verwendet werden. Der Server muss also nicht mehr Anfragen vom Client abwarten, sondern kann neue Informationen ausliefern, ohne auf eine neue Verbindung des Clients zu warten.
Ein Server-Push ist bei einer reinen HTTP-Verbindung nur durch verzögerte Antworten und Polling des Clients möglich. Zudem entfällt bei WebSockets der HTTP-Overhead, der bei jeder Anfrage einige Hundert Byte umfassen kann.
Wenn man nun beispielsweise an aufwendige Shooter-Spiele mit mehreren Mitspielern im Browser denkt, wird einem schnell klar das hier das HTTP-Protokoll fehl am Platz ist, da hier keine geringe Latenz geschaffen werden kann.
Der Anfang mit den WebSockets
Um eine Verbindung herzustellen, reicht es aus, den WebSocket Konstruktor aufzurufen:
// normal, "unsecure" connection var socket = new WebSocket('ws://localhost/echo'); // encrypted, "secure" connection var socket = new WebSocket('wss://localhost/echo');
Die WebSocket-Protokoll-Spezifikation definiert zwei neue URI-Schemen, ws:
für unverschlüsselte, und wss:
für verschlüsselte Verbindungen. Der WebSocket Konstruktor erlaubt auch die Angabe eines zweiten Arguments: optionale Subprotokolle. Dies kann ein String sein oder ein Array, bestehend aus Strings. Der WebSocket-Server muss dann entscheiden welches Subprotokoll verwendet werden soll. Die Subprotokoll Namen müssen eines der von IANA Registrierung festgelegten sein. Aktuell sind das SOAP oder WAMP.
Wenn Event-Listener an die Verbindung angehängt werden, kann sofort gesehen werden ob die Verbindung besteht, ein Fehler aufgetreten ist oder Mitteilungen eingetroffen sind.
// When the connection is open, send some data to the server socket.onopen = function () { socket.send('Ping'); // Send the message 'Ping' to the server }; // Log errors socket.onerror = function (error) { console.log('WebSocket Error ' + error); }; // Log messages from the server socket.onmessage = function (e) { console.log('Server: ' + e.data); };
Mit dem Server Kommunizieren
Sobald eine Verbindung zum Server besteht (open
-Event), können wir Daten mittels send('die Nachricht')
über das socket
-Objekt zum Server schicken. Dieses kann Strings sowie Binary-Messages verarbeiten. Um binary data zum Server zu schicken muss dies entweder ein ArrayBuffer
oder ein blob
-Objekt sein.
// Sending String socket.send('your message'); // Sending canvas ImageData as ArrayBuffer var img = canvas_context.getImageData(0, 0, 400, 320); var binary = new Uint8Array(img.data.length); for (var i = 0; i < img.data.length; i++) { binary[i] = img.data[i]; } socket.send(binary.buffer); // Sending file as Blob var file = document.querySelector('input[type="file"]').files[0]; socket.send(file);
Natürlich schickt uns auch der Server Nachrichten zu jeder Zeit. Wann immer dies passiert, wird der onmessage
-Callback gefeuert. Der Callback bekommt ein event
-Objekt und die eigentliche Nachricht ist über das data
Attribut erreichbar.
Status der Implementierung
Um mit WebSockets arbeiten zu können, bedarf es noch einen Browser der die Spezifikation implementiert hat. Ich gehe hier auf die letzte Spezifikation (RFC 6455) ein.
Internet Explorer | Firefox | Google Chrome | Safari | Opera |
---|---|---|---|---|
ab IE 10 PP5 | ab FF 11 | ab Chrome 16 | ab Safari 6 | ab Opera 10.5 |
In Opera sind WebSockets aber per Standard deaktiviert. Mozilla Firefox implementierte WebSockets bereits ab Version 6, allerdings als MozWebSocket
genannt.
Serverseitig
Aufgrund von WebSockets entstehen neue Interaktionsmöglichkeiten für serverseitige Anwendungen. Herkömmliche Server, wie LAMP, kommen oftmals mit einer großen Anzahl offener WebSocket-Verbindung nicht zurecht. Hierbei wird eine andere Architektur notwendig, die gleichzeitig eine hohe Anzahl an WebSocket-Verbindungen zulässt und keine Leistungseinbußen hat. Solche Architekturen werden meistens um Threading oder nicht-blockierende IOs konzipiert.
Serverseitige Implementierungen:
- Node.js
- Java
- Ruby
- Python
- Erlang
- C++
- .NET