Just in Time!

Realtime-Webapplikationen erstellen
Kommentare

Wenn der Benutzer nicht zu den Daten kommt, kommen die Daten eben zum Benutzer. Dieses Motto bildet die Grundlage für eine Vielzahl moderner Webapplikationen. Grundsätzlich besteht bei Webapplikationen das Problem, dass Sie als Benutzer im Frontend immer über einen aktuellen Datenstand verfügen möchten. Durch diese Forderung entstehen einige Anforderungen, die Ihre Applikation erfüllen muss, damit die Informationen, die Ihren Benutzern im Frontend zur Verfügung stehen, stets aktualisiert werden. Dieser Artikel zeigt, wie man solche Realtime Webapplications erstellen kann.

Die zusammenfassende Bezeichnung Real-Time-Webapplikations umfasst Webapplikationen, bei denen Informationen innerhalb der Applikation entstehen und sämtliche Clients über einen Mechanismus die neuen Daten erhalten und dem Benutzer anzeigen. Der Begriff Real Time bezeichnet dabei die Auslieferung der Informationen in einem angemessenen Zeitraum. Das bedeutet, dass zwischen der Entstehung der Daten und der Anzeige bei den Nutzern je nach Applikation einige Millisekunden bis mehrere Minuten liegen können.

Grundlagen

Die Grundlage für Webapplikationen bildet das HTTP-Protokoll. Es existiert bereits seit 1989, als es von Roy Fielding und Tim Berners-Lee am CERN entwickelt wurde. Da das Protokoll im Laufe der Zeit immer mehr an Bedeutung gewann, wurde es 1996 im RFC 1945 als HTTP/1.0 festgehalten. Dieser Standard wurde weiter überarbeitet, was schließlich zur Version HTTP/1.1 geführt hat, die bis heute gültig ist. Webapplikationen verwenden im Normalfall HTTP als Protokoll, mit dessen Hilfe die verschiedenen Ressourcen einer Applikation vom Benutzer angefragt und vom Server ausgeliefert werden. Auf Clientseite kommt ein Webbrowser zum Einsatz, der die Anfrage der notwendigen Ressourcen und Darstellung der angeforderten Seite übernimmt. Mittels URL wird die Ressource bei einem Webserver angefragt, der diese Anfrage verarbeitet und das Ergebnis entsprechend ausliefert. Ressourcen bedeuten bei einer Webapplikation nicht zwingend immer HTML-Seiten, sondern bezeichnen sämtliche Daten, die ein Server ausliefern kann. Das reicht von Mediendateien wie Bilder, Videos oder Audiodateien über Dokumente bis hin zu reinen Datenaustauschformaten wie XML-Dateien oder JSON-Dokumenten.

In HTTP sind beide Rollen, Client und Server, strikt getrennt. Der Client fragt eine Ressource an, der Server antwortet und liefert die gewünschte Ressource aus. Dieses Wechselspiel hat jedoch den Nachteil, dass der Server von sich aus über keinerlei Möglichkeit verfügt, mit einem Client aktiv zu kommunizieren. Diese aktive Form der Kommunikation ist allerdings eine Grundvoraussetzung, damit eine Real-Time-Webapplikation funktionieren kann. Der Server muss dem Client melden, wenn neue Daten verfügbar sind. Diese Aufgabe kann HTTP jedoch nicht oder maximal ungenügend erfüllen. Im Laufe der Zeit entwickelten sich zahlreiche Lösungen, die aus einfachen Webapplikationen echtzeitfähige Applikationen machen und sie so ein großes Stück näher an Desktopapplikationen rücken.

Geschichte

Schon im Jahr 1996 war klar, dass es notwendig ist, nicht nur vom Client aus mit dem Server zu kommunizieren, sondern einen bidirektionalen Kommunikationskanal offen zu halten. Zu dieser Zeit war noch nicht absehbar, welche Programmiersprache sich im Browser durchsetzen wird. JavaScript steckte zu dieser Zeit nach seiner Einführung im Jahr 1995 noch in den Kinderschuhen. Noch waren Java Applets häufig auf den verschiedenen Webseiten anzutreffen. Und ihre Einbindung in eine Webseite machte es den Entwicklern auch möglich, den Server aktiv mit den Clients kommunizieren zu lassen. Im Verlauf der Entwicklung zeichnete sich jedoch ab, dass Java Applets sich nicht gegen JavaScript als clientseitige Programmiersprache durchsetzen konnten. In den Jahren zwischen 2000 und 2006 wurden verschiedenste Lösungsansätze entwickelt, die die bidirektionale Kommunikation zwischen Client und Server ermöglichen sollten. 2006 jedoch etablierte Alex Russell in einem Blogartikel die Bezeichnung Comet.

Comet bezeichnet Methoden, mit denen über verschiedene Mittel, HTTP-Verbindungen zum Server über längere Zeit offen gehalten werden und so dem Server ermöglicht wird, mit dem Client zu kommunizieren. Das Ziel von Comet war, wie auch schon bei AJAX, bestehende Technologien zu verwenden, um eine neue Problemlösung umzusetzen. Beide Bezeichnungen, also sowohl AJAX als auch Comet, stammen ursprünglich von in den USA weitverbreiteten Haushaltsreinigern. Mit Comet war es schließlich möglich, ohne störende Browser-Plug-ins erste echtzeitfähige Applikationen umzusetzen. Die Entwicklung endete jedoch nicht mit dem Auftreten von Comet.

Mittlerweile gibt es mit dem WebSocket-API Versuche des W3C ein eigenes Kommunikationsprotokoll, das auf der gleichen Ebene wie HTTP arbeitet, zu standardisieren und etablieren. Das WebSocket-API wird im Zuge von HTML5 entwickelt, und es liegt ein eigener RFC vor, der das Protokoll standardisiert. Im Laufe dieses Artikels lernen Sie verschiedene Arten kennen, wie Sie echtzeitfähige Webapplikationen umsetzen können.

Comet

Die einfachste Variante, neue Inhalte auf einer Webseite darzustellen, besteht darin, dass der Client in bestimmten Zeiträumen beim Server nachfragt, ob aktualisierte Daten vorliegen. Diese Variante kann ganz einfach umgesetzt werden, indem Sie innerhalb der setInterval-Funktion eine Callback-Funktion definieren, in der per AJAX Request immer wieder beim Server nachgefragt wird. Der Server meldet dann entweder zurück, dass sich nichts geändert hat oder liefert die aktualisierten Daten. Der Clientcode muss sich dann nur noch darum kümmern, die Aktualisierung im DOM vorzunehmen und sie so dem Benutzer anzuzeigen. Diese Variante hat jedoch einen entscheidenden Nachteil: Um einen Real-Time-Effekt zu erzielen, benötigen Sie sehr viele Requests an den Server. Das bedeutet, dass Sie im Idealfall alle zehn Sekunden beim Server nachfragen, ob sich Daten geändert haben. Bei einer einstelligen Anzahl von Clients, die auf Ihre Applikation zugreifen, ist das noch kein Problem. Steigt die Nutzeranzahl jedoch, wird diese Anzahl an Anfragen zum Problem für Ihre Infrastruktur. Allein schon das Bootstrapping bei jedem Request benötigt so viele Ressourcen, dass diese Variante als Implementierung in einer Real-Time-Webapplikation ausscheidet.

Mit Comet wurde dieser Ansatz entscheidend verbessert. Die vielen einzelnen Anfragen wurden durch länger andauernde Anfragen ersetzt. Bei dieser Lösung wird auf ein Feature von HTTP zurückgegriffen, das es erlaubt, Verbindungen bis zur Antwort des Servers oder einem festgelegten Time-out-Wert offen zu halten. Erhält der Client die Antwort oder wird die Verbindung unterbrochen, wird erneut eine Verbindung zum Server geöffnet, sodass ein permanent geöffneter Kanal simuliert wird.

Die Umsetzung im Browser findet in den meisten Fällen als AJAX Request statt. Hier wird vom Browser ein asynchroner XHR Request zum Server gesendet. Antwortet der Server vor dem Verbindungs-Time-out, wird diese Antwort verarbeitet. In jedem Fall, egal ob eine Antwort vorliegt oder ein Time-out auftritt, wird eine neue Verbindung aufgebaut. Als Entwickler müssen Sie sich jedoch weder um die Implementierung des Servers noch des Clients kümmern. Zu diesem Zweck existieren zahlreiche Bibliotheken, die Sie problemlos in Ihr Projekt einbinden und nutzen können.

Ein gutes Beispiel für die serverseitige Umsetzung von Comet ist das CometD- Projekt der Dojo Foundation. Clientseitig existieren Umsetzungen sowohl für das Dojo Toolkit als auch für jQuery. Die Comet- Implementierung geht von einem System von Channels aus, auf das sich die verschiedenen Clients subscriben können, um Daten zu empfangen. Die Channels bilden auf der anderen Seite auch die Grundlage zum Senden der Daten. Das bedeutet, dass ein Client die Daten an einen bestimmten Channel sendet und sämtlichen anderen Clients, die auf diesen Channel verbunden sind, können diese Nachricht empfangen. Auch der Sicherheitsaspekt wird vom CometD abgedeckt. So definieren Sie eine SecurityPolicy, innerhalb derer Sie festlegen können, welcher Client welche Aktionen durchführen darf. Diese Aktionen umfassen die Durchführung des Handshakes, der für den Verbindungsaufbau notwendig ist, das Erstellen von neuen Channels sowie das Publishen und Subscriben auf einem bestimmten Channel. Mit den angesprochenen Komponenten können Sie nun beide Seiten, also sowohl Client als auch Server, abdecken. Ein wichtiger Teil fehlt in diesem System allerdings noch: die Datenquelle.

In den meisten Fällen wird Comet als Ergänzung einer Webapplikation eingesetzt. Das bedeutet, dass Ihre eigentliche Applikation in einer Skriptsprache wie PHP umgesetzt ist. Die Clients greifen über HTTP auf den Webserver zu und erhalten Dokumente in den verschiedensten Formaten, erstellen, verändern oder löschen Informationen auf dem Server. Diese schreibenden Zugriffe sollen nun an die Clients übermittelt werden. Zu diesem Zweck existieren einige Bibliotheken, die Sie in Ihre Applikation einbinden können, um die geänderten Informationen per Publish an den jeweiligen Channel zu senden. Mit diesem System können Sie sowohl neue als auch bestehende Applikationen mit relativ geringem Aufwand auf der Serverseite um Real-Time-Fähigkeit ergänzen.

Clientseitig stellt diese Erweiterung eine wesentlich größere Herausforderung dar, da korrekt mit den Aktualisierungen umgegangen werden muss. Doch zu diesem Thema und den entsprechenden Strategien später mehr. Allen guten Konzepten zum Trotz befindet sich Comet im Abstieg und verliert immer mehr an Bedeutung gegenüber moderneren Technologien wie beispielsweise dem WebSocket-API.

WebSockets

Ein typischer Anwendungsfall und ein gern gewähltes Beispiel für echtzeitfähige Webapplikationen ist ein Chat, der auf einer Webseite eingebunden wird. In den folgenden Abschnitten erfahren Sie, wie Sie einen einfachen Multiclientchat in Node.js umsetzen können. Die Implementierung der Applikation in einer traditionellen Skriptsprache für Webapplikationen wie PHP ist problematisch, da PHP eigentlich eine Request-basierte Sprache und standardmäßig nicht für langlaufende Prozesse ausgelegt ist. Es ist zwar möglich, eine derartige Applikation komplett in PHP umzusetzen. Für den Zweck der Echtzeitkommunikation haben sich jedoch in der Praxis Hybridlösungen etabliert. Chatlösungen wie auch andere Real- Time-Webapplikationen bestehen, wie bereits mit Comet skizziert, meist aus mehreren Komponenten. Die eigentliche Applikation mit der gesamten Businesslogik wird in einer Skriptsprache wie PHP umgesetzt. Für die Kommunikationskomponente kommen Lösungen wie Node.js, XMPP oder Ähnliches zum Einsatz.

Lassen Sie Benutzer, die ältere Browser verwenden, außen vor, können Sie Ihre Real-Time-Webapplikation mit WebSockets umsetzen. Diese Technologie wird mittlerweile von allen gängigen Browsern wie Chrome, Firefox, Opera und Safari in ihrer aktuellen Version unterstützt. Sogar der Internet Explorer in der Version 10 verfügt über WebSocket-Support.

WebSockets sind kein reines Browserfeature, wie viele andere Bestandteile von HTML5, sondern eine Spezifikation für ein Kommunikationsprotokoll zwischen Client und Server, bei dem, im Gegensatz zu HTTP, beide Seiten gleichberechtigt sind. Zur Verwendung von WebSockets müssen Sie keine weiteren Plug-ins in Ihrem Browser installieren. Sie können hier auf native JavaScript-Schnittstellen zurückgreifen. Serverseitig können Sie im Falle von Node.js auf verschiedene Bibliotheken wie beispielsweise das NPM-Paket websocket zurückgreifen. Im ersten Schritt sehen Sie nun in Listing 1, wie Sie einen leichtgewichtigen Chatclient umsetzen können.

Listing 1

 < 
    <script src="<a class="elf-external elf-icon" href="http://code.jquery.com/jquery-1.9.1.min.js" rel="nofollow">http://code.jquery.com/jquery-1.9.1.min.js</a>"></pre>
<div id="msgs" style="height: 400; width: 400; overflow: scroll;"></div>
<form id="chatForm"><button id="sendBtn">Send</button></form>
<pre class="brush: xml; auto-links: true; collapse: false; first-line: 1; html-script: false; smart-tabs: true; tab-size: 4; toolbar: true; codetag" title="Listing 1">
    
      var socket = new WebSocket('ws://localhost:8080/', 'chat');

      $('#sendBtn').on('click', function (e) {
        e.preventDefault();
        var name = $('#name').val(),
        msg = $('#msg').val();

        socket.send('{"name": "' + name + '", "msg": "' + msg + '"}');
      });

      socket.onmessage = function (msg) {
        var data = JSON.parse(msg.data),
        content = $('#msgs').html() + ' ';
        $('#msgs').html(content + data.name + ': ' + data.msg);
      };

Für diese Implementierung benötigen Sie nur sehr wenig HTML. Über ein Formular können Sie Ihren Namen und die Nachricht eingeben und diese dann per Button absenden. Die Nachrichten, die Sie selbst oder andere Personen verfasst haben, werden dann in einem div-Container dargestellt. Für ein einfacheres Handling der notwendigen DOM- Operationen sollten Sie eine minifizierte Version von jQuery einbinden. Diese ist zum Beispiel hier verfügbar. Die eigentliche Logik des Chatclients wird innerhalb der script-Tags am Ende der Datei definiert. Im ersten Schritt erzeugen Sie eine Instanz eines WebSockets, indem Sie den Konstruktor mit dem Ziel-URL und einem optionalen Subprotokoll aufrufen. Mithilfe dieses Objekts können Sie dann mit dem Server in Verbindung treten. Die erste Aktion, die Sie dann implementieren, ist das Absenden der Werte des Formulars als Zeichenkette im JSON-Format über die bestehende WebSocket-Verbindung mit einem Aufruf der send– Methode.

Der zweite Teil der Logik besteht darin, mit Antworten des Servers umzugehen. Das WebSocket-API sieht hierfür die Eigenschaft onmessage vor, der Sie als Wert eine Funktion zuweisen können, die ausgeführt wird, sobald eine Nachricht vom Server vorliegt. Dieser Quellcode reicht aus, um einen sehr einfachen Chatclient zu realisieren. Alles, was Sie nun noch zu tun haben, ist die Serverseite zu implementieren. In Listing 2 sehen Sie den entsprechenden Quellcode.

Listing 2

var WebSocketServer = require('websocket').server;

var server = require('http').createServer(function(req, res) {
  require('fs').readFile('client.html', function (e, data) {
    res.end(data.toString());
  });
}).listen(8080);

wsServer = new WebSocketServer({
  httpServer: server
});

var connections = [];

wsServer.on('request', function(request) {
  var connection = request.accept('chat', request.origin);

  connections.push(connection);

  connection.on('message', function(message) {
    for (var i = 0; i < connections.length; i++) {
      if (connections[i] && connections[i].send) {
        connections[i].send(message.utf8Data);
      }
    }
  });
});

Die Serverseite wird, wie auch schon der Client, in JavaScript umgesetzt. Damit Sie den Server auf Ihrem System ausführen können, müssen Sie Node.js installieren. Node.js als serverseitige JavaScript-Plattform ist sowohl auf Linux wie auch auf Windows und Mac OS lauffähig. Hier können Sie sich den jeweiligen Installer für Ihr System herunterladen. Die zweite Voraussetzung besteht aus dem NPM-Paket websocket, das Ihnen sowohl die Umsetzung von WebSocket-Servern wie auch -Clients erlaubt. Mit Node.js wird auf Ihrem System auch der Node Package Manager, kurz NPM, installiert, mit dessen Hilfe Sie die Pakete verwalten können. Die Installation des Pakets erfolgt über das Kommando npm install websocket.

Der Server muss zwei Funktionen parallel erfüllen. Zum einen muss die HTML-Seite, die den Clientcode enthält, auf Anfrage des Clients ausgeliefert werden und zum anderen muss der Server eingehende WebSocket-Verbindungen akzeptieren. Da das WebSocket-Modul den HTTP-Server von Node.js benötigt, um funktionieren zu können, können beide Funktionen in einer Datei erfüllt werden.

Die Umsetzung des Servers beginnen Sie im Normalfall damit, die Abhängigkeiten zu laden. In Node.js erreichen Sie dies jeweils über einen Aufruf der require-Funktion, der Sie den Namen des zu ladenden Moduls übergeben. Für die Umsetzung des Servers benötigen Sie das interne http-Modul von Node.js und das installierte NPM-Paket websocket. Nachdem Sie beide Module eingebunden haben, gilt es im ersten Schritt, die anfragenden Clients mit dem Quellcode der Applikation zu versorgen. Sie erreichen dies, indem Sie im Aufruf der createServer-Methode eine Callback-Funktion mitgeben, die später aufgerufen wird, sobald eine Anfrage eines Clients eingeht. Diese Callback-Funktion erhält beim Aufruf sowohl ein Request- als auch ein Response-Objekt. Im Falle der Chatapplikation ist nur das Response-Objekt von Bedeutung. Es stellt die Antwort an den Client dar und ist damit die Stelle der Applikation, an der Sie den Quellcode für den Chatclient ausliefern können. Damit Sie die HTML-Datei an den Client senden können, müssen Sie die Datei mit dem fs-Modul von Node.js und der readFile-Methode vom Dateisystem lesen und über einen Aufruf der end-Methode des Response-Objekts an den Client senden. Auf dem Objekt, das die createServer-Methode zurückliefert, müssen Sie dann nur noch die listen-Methode aufrufen und dabei die Nummer des Ports angeben, auf den der Server gebunden werden soll.

Im Beispiel ist das Port 8080. Speichern Sie die Datei unter dem Namen server.js und führen Ihre Applikation mit dem Kommando node server.js aus, können Sie mit einem Webbrowser auf Ihrem System den URL localhost:8080 aufrufen und erhalten den Quellcode Ihres Chatclients. Mit diesem Stand ist die Chatapplikation allerdings noch nicht voll funktionsfähig. Es fehlt noch an der serverseitigen WebSocket-Unterstützung. Zuerst müssen Sie hier eine Instanz des WebSocket-Servers erzeugen. Der Konstruktor akzeptiert eine Objektstruktur mit einigen Konfigurationsdirektiven. Die entscheidende Option ist im Beispiel der HTTP-Server. Über diese werden beide Server miteinander verbunden. Da jede WebSocket-Verbindung für sich steht, die Clients sich allerdings untereinander unterhalten können sollen, benötigen Sie eine Struktur mit deren Hilfe Sie jederzeit Zugriff auf die einzelnen WebSockets haben. Im Beispiel ist dies ein Array, das sämtliche Sockets enthält. Bei jeder neuen Verbindung wird eine Referenz auf die Verbindung in diesem Array gespeichert. Der gesamte WebSocket-Server ist Event-basiert umgesetzt. Das bedeutet, dass Sie, wie in JavaScript üblich, Callback-Funktionen für bestimmte Ereignisse registrieren. Konkret benötigen Sie eine Callback-Funktion für das request-Event. In dieser Funktion haben Sie Zugriff auf das request-Objekt des WebSockets. Über die accept-Methode gelangen Sie an die Verbindung. Diese wiederum bietet Ihnen Zugriff auf das message-Event, das ausgelöst wird, sobald eine neue Nachricht auf dem WebSocket eingeht. Innerhalb der Callback-Funktion des message-Events haben Sie nun die Möglichkeit, die eingehende Nachricht an alle WebSockets weiterzuleiten, die sich in Ihrem Array befinden. Der Aufruf der send-Methode auf dem jeweiligen WebSocket bewirkt, dass die Clients die Nachricht erhalten und den Text entsprechend darstellen.

Der entscheidende Nachteil des WebSocket-API ist, dass nicht alle Browser dieses Feature unterstützen. Besteht ein wichtiger Teil Ihrer Applikation aus der bidirektionalen Kommunikation über WebSockets, ist dieses Feature unter Umständen für einige Benutzer nicht verfügbar oder Sie implementieren für diese Benutzer eine Alternative.

Socket.IO

Diese Alternative zur Unterstützung von Browsern, die das WebSocket-API nicht implementieren, können Sie entweder über eine Browserweiche selbst umsetzen, oder Sie greifen auf eine vorhandene Bibliothek zurück, die diese Aufgabe für Sie übernimmt. Einer der am weitesten verbreiteten Vertreter ist Socket.IO.

Das primäre Ziel dieser Bibliothek ist, Real-Time-Webapplikationen auch für ältere Browser und bestimmte mobile Browser zu ermöglichen, die WebSockets nicht unterstützen. Zu diesem Zweck verfügt die Bibliothek über mehrere Fallback-Mechanismen. Das bedeutet für Sie, dass eine andere Technologie verwendet wird, falls WebSockets nicht verfügbar sind. Die Alternativen sind hier Flash Sockets, JSONP Polling und AJAX Long Polling. Um die Aushandlung und Selektion der passenden Technologie müssen Sie sich als Entwickler nicht kümmern. Socket.IO stellt Ihnen zu diesem Zweck eine einheitliche Schnittstelle zur Verfügung, sodass Sie im Normalfall nicht merken, welche Technologie verwendet wird. Damit das Chatbeispiel nun auf Socket.IO funktioniert, müssen Sie einige Änderungen am Quellcode durchführen. Listing 3 zeigt Ihnen den modifizierten Server.

Listing 3

var server = require('http').createServer(function(req, res) {
  require('fs').readFile('client.html', function (e, data) {
    res.end(data.toString());
  });
}).listen(8080);

var io = require('socket.io').listen(server);

io.sockets.on('connection', function (socket) {
  socket.on('message', function (data) {
    socket.emit('message', data);
    socket.broadcast.emit('message', data);
  });
});

Damit das Beispiel funktionieren kann, müssen Sie zuerst Socket.IO installieren. Dies geschieht über das Kommando npm install socket.io. Danach können Sie den Code des Servers entsprechend modifizieren. Die Auslieferung des Clientquellcodes bleibt unverändert bestehen. Sie müssen nun statt dem websocket-Modul das socket.io-Modul einbinden.

Die Behandlung der Verbindung gestaltet sich etwas anders. Socket.IO ist wie schon das websocket-Modul auch eventbasiert aufgebaut. Das bedeutet, dass bei jeder eingehenden Verbindung ein connection-Event ausgelöst wird. Auf dieses Event können Sie eine Callback-Funktion registrieren. Innerhalb dieser Callback-Funktion binden Sie wiederum eine Callback-Funktion auf das message-Event, das durch den Client ausgelöst wird, wenn dieser eine Nachricht sendet. Sie können dieses Ereignis im Gegensatz zu WebSockets beliebig benennen. Das Versenden von Nachrichten an alle verbundenen Sockets geschieht über die broadcast.emit-Methode, die die Nachricht an alle Sockets bis auf den aktuell verbundenen sendet. Aus diesem Grund müssen Sie ein einfaches emit zusätzlich aufrufen, falls Sie an den verursachenden Socket ebenfalls die Nachricht versenden möchten. Mit diesen Anpassungen ist der Server voll funktionsfähig. Die übrigen Änderungen betreffen den Client. Diese sehen Sie in Listing 4.

Listing 4

  
    <script src="<a class="elf-external elf-icon" href="http://code.jquery.com/jquery-1.9.1.min.js" rel="nofollow">http://code.jquery.com/jquery-1.9.1.min.js</a>">
    <script src="<a class="elf-external elf-icon" href="http://localhost:8080/socket.io/socket.io.js" rel="nofollow">http://localhost:8080/socket.io/socket.io.js</a>"></pre>
<div id="msgs" style="height: 400; width: 400; overflow: scroll;"></div>
<form id="chatForm"><button id="sendBtn">Send</button></form>
<pre class="brush: php; auto-links: true; collapse: false; first-line: 1; html-script: false; smart-tabs: true; tab-size: 4; toolbar: true; codetag">    
      var socket = io.connect('<a class="elf-external elf-icon" href="http://localhost:8080" rel="nofollow">http://localhost:8080</a>');

      $('#sendBtn').on('click', function (e) {
        e.preventDefault();
        var name = $('#name').val(),
        msg = $('#msg').val();

        socket.emit('message', '{"name": "' + name + '", "msg": "' + msg + '"}');
      });

      socket.on('message', function (msg) {
        var data = JSON.parse(msg),
        content = $('#msgs').html() + ' ';
        $('#msgs').html(content + data.name + ': ' + data.msg);
      });

Die Änderungen im Client halten sich ebenfalls in Grenzen. Sie müssen zusätzlich zu jQuery die Socket.IO-Clientbibliothek einbinden. Die Auslieferung übernimmt Socket.IO automatisch. Die Verbindung wird über die connect-Methode hergestellt. Zum Versenden einer Nachricht müssen Sie statt der send-Methode bei WebSockets die emit-Methode benutzen. Neben der zu versendenden Nachricht geben Sie hier außerdem die Bezeichnung der Nachricht, in diesem Fall die Zeichenkette message, mit. Der Empfang der Nachricht erfolgt wieder eventbasiert. Sie müssen lediglich eine Callback-Funktion auf das message-Event registrieren. Nun können Sie den Server starten und sich mit Ihrem Browser über http://localhost:8080 auf den Server verbinden.

Vom Beispiel in die reale Welt

Das Beispiel eines Multiclientchats ist nur eine von vielen Möglichkeiten, wie eine Real-Time-Webapplikation aussehen kann. Dieses Beispiel verdeutlicht allerdings sehr gut die Verwendung der verschiedenen Methoden, die Sie auch in jeder anderen Applikation benötigen. Implementieren Sie eine Webapplikation, müssen Sie Teile der Darstellung beim Client aktualisieren, sobald neue oder geänderte Daten vorliegen. Um das zu erreichen, haben Sie mehrere Möglichkeiten: Die einfachste Variante ist, dass Sie dem Client eine Aufforderung zum kompletten Neuladen der Seite schicken. Diese Lösung hat jedoch einige unschöne Nebeneffekte. Erstens entsteht viel Traffic durch das Neuanfordern der kompletten Seite, was erhöhte Last auf dem Server bedeutet, was noch relevanter wird, wenn Ihre Applikation von vielen Nutzern gleichzeitig verwendet wird, da alle Nutzer die Nachricht gleichzeitig erhalten und die Anfragen an den Server ebenfalls gleichzeitig gesendet werden. Eine bessere Umsetzung besteht darin, dass Sie Ihre Seite in bestimmte Teile, so genannte Widgets, unterteilen und diese neu laden, falls neue Daten verfügbar sind. Das gibt Ihnen die Möglichkeit, nur die Teile für die Echtzeitkommunikation zu aktivieren, bei denen es wirklich notwendig ist. Die eleganteste Möglichkeit, wie Sie Ihre Applikation echtzeitfähig machen können, ist, wenn Sie die Daten, die neu dargestellt werden sollen, gleich vom Server ausliefern lassen und sich der Client vollständig um ihre korrekte Darstellung kümmert. In dieser Implementierung nutzen Sie gleich mehrere Vorteile aus. Zum Zeitpunkt der Benachrichtigung weiß der Server, welche Daten wie modifiziert wurden, also, ob es sich um einen neuen Datensatz, eine Änderung oder eine Löschung handelt. Außerdem verfügt der Server über die betroffenen Daten. Diese können als Paket zu den Clients gesendet werden. Erhält ein Client eine Benachrichtigung über einen neuen Datensatz, kann er diesen einfach an der korrekten Stelle einfügen. Bei einer Änderung müssen Sie einen Mechanismus vorsehen, wie Sie punktuell auf die Visualisierung eines Datensatzes zugreifen können, um die dargestellten Daten auszutauschen. Gleiches gilt für das Löschen eines Datensatzes.

Setzen Sie ein öffentliches Informationsportal um, das echtzeitfähig sein soll, haben Sie kein Problem mit vertraulichen Daten, da diese für alle Nutzer gleichermaßen zugänglich sind. Schwieriger wird die Situation, wenn es sich bei den Daten um vertrauliche Informationen handelt. Broadcasten Sie derartige Informationen, wird das Vertrauen in Ihre Applikation schnell verloren gehen, im schlimmsten Fall entsteht gar wirtschaftlicher Schaden. Zur Absicherung sollten Sie statt dem HTTP- und dem WebSocket- Protokoll die jeweils sichere Variante verwenden, also https:// und wss://.

Zur weiteren Absicherung können Sie die Autorisierung pro Namespace vornehmen. Das bedeutet, dass sich nur berechtigte Benutzer auf einen Namespace subscriben dürfen. Über die Kombination der of-Methode von Socket.IO mit dem Namen eines Namenspaces und der authorization-Methode können Sie eine Callback-Funktion registrieren, innerhalb derer Sie Zugriff auf die Handshake-Daten haben.

Verwenden Sie PHP in Verbindung mit Socket.IO, können Sie beispielsweise über die Session-ID eines Clients personalisierte Sockets aufbauen und gezielt Ihre Clients ansprechen. Dies ermöglicht es Ihnen außerdem, den Zugriff auf bestimmte Namespaces von Ihrer Applikation in PHP zu steuern.

Zusammenfassung

Real-Time-Webapplikationen sind immer häufiger anzutreffen. Einige prominente Beispiele sind Facebook oder Twitter. Aber auch Sie haben die Möglichkeit, mit Technologien wie dem WebSocket-API eine echtzeitfähige Webapplikation zu erstellen. Bibliotheken wie Socket.IO nehmen Ihnen dabei einen Teil der alltäglich anfallenden Arbeiten ab und helfen Ihnen bei der Unterstützung von älteren Browsern. Grundsätzlich gilt allerdings, eine Applikation nachträglich zu einer echtzeitfähigen Applikation umzurüsten, ist meist sehr schwierig, da hier die Architektur an vielen Stellen im Weg steht.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -