smart | Webentwicklung
Alles rund um HTML5, PHP, WordPress & Co.

Einsatz von HTML5 Server-Sent Events

28. August 2012
Stephan
Vorstellung von HTML5 Server-Sent Events

Ein Schattendasein hinter der HTML5 WebSocket-Technologie führt die auch im Rahmen von HTML5 spezifizierte Server-Sent Events (SSEs)-Technik.

Dabei handelt es sich um eine reine Server-Push-Technik bei der der Webbrowser eine unidirektionale HTTP-Verbindung zum Server offen hält.

Über die offene Verbindung kann der Server jederzeit Nachrichten an den Client schicken, ohne dass die Verbindung wie z. B. beim Long-Polling zwischendurch getrennt und wieder neu hergetellt werden muss. Wobei hier angemerkt werden muss, dass auch klassisches Polling hiermit durchaus möglich ist.

In diesem Artikel möchte ich euch nun zeigen, wie ihr HTML5 Server-Sent Events einsetzen bzw. implementieren könnt.

Clientseitige Implementierung

Die clientseitige Implementierung ist analog zu der HTML5 WebSockets-Implementierung sehr einfach gehalten und durch das W3C spezifiziert. Dazu mal folgender JavaScript-Code als Beispiel:

var eventSource;

if(!!window.EventSource) 
{
	eventSource = new EventSource('my-event-source.php');
} else {
	alert('Dein Browser untestützt keine HTML5 Server-Sent Events');
}

eventSource.addEventListener('open', function(event) 
{
	console.log('Verbindung wurde erfolgreich hergestellt.');
});

eventSource.addEventListener('message', function(event) 
{
	console.log('Nachricht: ' + event.data);
});

eventSource.addEventListener('error', function(event) 
{
	if (event.readyState == EventSource.CLOSED) 
	{
		console.log('Es ist ein Fehler aufgetreten. Die Verbindung wurde getrennt.');
	}
});

Wir machen nichts weiter als erst zu überprüfen, ob HTML5 Server-Sent Events vom verwendeten Webbrowser unterstützt werden (Zeile 3 – 8). Dazu nutzen wir einfach eine doppelte Negation.

Anschließend werden die Event-Handler definiert. Wenn die Verbindung zum Server erfolgreich hegestellt wurde, dann wird der open-Event-Handler gefeuert und dessen angegebene Callback-Methode ausgeführt (Zeile 10 – 13).

In unseren Fall lassen wir uns die Verbindungsherstellung in der Konsole ausgeben. Analog arbeitet der onmessage– bzw. onerror-Event-Handler (Zeile 15 – 26).

Bei einer eingehenden Nachricht, die der Server gesendet hat, ist diese über das event-Objekt unter data abrufbar.

Die genaue W3C-Spezifikation bzw. das sogenannte Working Draft findet ihr auf der Website des W3C: www.w3.org

Serverseitige Implementierung

Auf Serverseite kann nun ein Skript z. B. unendlich ausgeführt werden, um ständig aktuelle Daten zum Client zu schicken. Wichtig ist, dass der Server die Nachricht mittels dem Content-Type text/event-stream überträgt.

Dazu solltet man noch angeben, dass kein Caching seitens des Webbrowsers stattfinden soll. Dazu folgendes PHP-Beispiel:

header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

while(1)
{
	$time = date('r');
	echo "data: {$time}\n\n";
	flush();
}

Wir haben hier eine unendliche Schleife, die uns immer die aktuelle Server-Zeit zum Client schickt. Die Sinnhaftigkeit dessen sei jetzt hier mal dahingestellt, aber das Beipsiel soll euch ja nur zeigen, wie einfach die serverseitige Implementierung ist.

Außerdem ist anzumerken, dass jede Nachricht mit dem Präfix data: eingeleitet wird. Anschließend wird der eigentliche Text der Nachricht angegeben und abgeschlossen wird die Nachricht mit einer Newline-Sequenz (\n\n).

Weiterhin ist zu beachten, dass wenn das Server-Skript endlich ist, wird am Ende der Ausführung die Verbindung getrennt. Jedoch stellt der Webbrowser standardmäßig nach ca. 3 Sekunden (je nach Browser-Implementierung kann das ein wenig abweichen) die Verbindung wieder her und das Skript wird erneut ausgeführt.

Das oben gezeige Server-Skript würde also auch ohne die while-Schleife funktionieren und uns immer alle 3 Sekunden die aktuelle Serverzeit zum Client senden.

Zeit für erneutes Verbinden des Webbrowsers ändern

Wenn das Server-Skript endlich ist, verbindet sich der Webbrowser, wie bereits eben erwähnt, nach etwa 3 Sekunden wieder mit dem Server. Diese Zeit können wir aber auch mit retry ändern:

header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

$time = date('r');
echo "retry: 10000\n" . 
     "data: {$time}\n\n";
flush();

Dabei wird die Zeit in Millisekunden angegeben. In diesem konkreten Beispiel wird die Server-Zeit nun nur noch alle 10 Sekunden an den Client geschickt, weil sich der Webbrowser erst nach 10 Sekunden wieder mit dem Server verbindet.

Individuelle HTML5 Server-Sent Events festlegen

Eine weitere Funktionalität beim Einsatz von HTML5 Server-Sent Events ist, dass wir individuelle Events festlegen können, auf dir wir mit einem eigenen Event-Handler unterschiedlich reagieren können.

Dazu können wir serverseitig mittels event: eine Nachricht einem bestimmten Event zuordnen:

header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

$time = date('r');
echo "event: servertime\n" . 
     "data: {$time}\n\n";
flush();

Nun können wir clientseitig einen neuen Event-Handler definieren, der immer bei eintreffenden servertime-Events ausgelöst wird. Dazu ergänzen wir unseren clientseitigen JavaScript-Code und fügen Folgendes hinzu:

eventSource.addEventListener('servertime', function(event) 
{
    console.log('Serverzeit: ' + event.data);
});

Durch die Möglichkeit individuelle Events zu definieren, ist es ein Leichtes auf unterschiedliche Nachrichtentypen verschiedenartig zu reagieren.

Browser-Kompatibilität

HTML5 Server-Sent Events werden derzeit in allen gängigen Browsern, mit Ausnahme des Internet Explorers unterstützt.

Den aktuellen Stand zur Browser-Kompatibilität findet ihr hier: caniuse.com

Fazit

Wie ihr sehen könnt, lässt sich die Technik der HTML5 Server-Sent Events sowohl auf Client- als auch Serverseite relativ leicht umsetzen. Damit kann es als sinnvolle AJAX-Alternative verwendet werden, wenn es darum geht, dass der Client nicht ständig Daten zum Server senden muss, sondern der Fokus darauf liegt, dass der Client nur Updates vom
Server erhält.

Im Gegensatz zu HTML5 WebSockets benötigt ihr kein spezifisches Protokoll und auch keine spezielle serverseitige Implementierung. Des Weiteren besticht die Server-Sent Events-Technik durch sinnvolle Funktionen, wie z.B. dem Wiederverbinden bei zusammengebrochenen Verbindungen und der Möglichkeit Event-IDs zu vergeben und somit individuell auf verschiedene Events reagieren zu können.

Weiterführende Informationen und mehr Details zu HTML5 Server-Sent Events findet ihr auf: www.html5rocks.com

Habt ihr selbst schon mal mit HTML5 Server-Sent Events gearbeitet? Was haltet ihr von dieser Technik? Schreibt mir doch einfach ein Kommentar mit euren Erfahrungen.

Kommentare  
3 Kommentare vorhanden
1 Fumar Porros schrieb am 19. Februar 2013 um 14:02 Uhr

In Deinem ersten Script-Beispiel muss das korrigiert werden:
console.log(‚Nachricht: ‚event.data);
Da fehlt ein Pluszeichen… 🙂

Ansonsten gut erklärt… ^^

2 Stephan L. schrieb am 19. Februar 2013 um 16:20 Uhr

Freut mich, dass der Artikel der Gefallen hat.

Ach und danke dir frü den Hinweis! Habe ich gleich mal korrigiert. 😉

Grüße

Stephan

3 Carsten schrieb am 19. Mai 2014 um 15:23 Uhr

Vielen Dank für den anschaulichen Artikel.
Was mir allerdings noch nicht ganz klar ist:
SSE dient doch in erster Linie dazu, dass der Client (Browser) auf Events vom Server reagiert. Dies setzt doch voraus, dass auf dem Server alle x Sekunden eine Routine gestartet wird, die das Ergebnis an den Client feuert (ala Broadcast).

Oben steht:
„Wenn das Server-Skript endlich ist, verbindet sich der Webbrowser, wie bereits eben erwähnt, nach etwa 3 Sekunden wieder mit dem Server. Diese Zeit können wir aber auch mit retry ändern“
Warum verbindet sich der Browser AKTIV alle 3 Sekunden mit dem Server? Der Browser soll doch (nur) darauf ‚lauern‘, bis der Event „servertime“ vorbei kommt, also selbst nicht aktiv tätig werden!?!?

0 Trackbacks/Pingbacks vorhanden
Du bist herzlich eingeladen auch ein Kommentar zu hinterlassen!
Kommentar schreiben

Vielen Dank für dein Kommentar!