Das »Web2.0« mit seiner neuen (alten) Technologie Ajax macht viele Webseiten zu komplexen Programmen. Webseiten können zur Laufzeit verändert und mit dynamischen Inhalten gefüttert werden. Doch Ajax ist nicht unbedingt geeignet für jede Webanwendung, da es immer noch zwei Verbindungen benötigt: Einen Up-Stream für die GET- oder POST-Anfrage und einen Downstream für die Response.
Wer beispielsweise schon einmal mit Google Wave gespielt hat, wird merken, dass eingegebene Zeichen (mit sehr kurzer Verzögerung) auf dem Bildschirm des Gesprächspartners erscheinen. Wer so etwas mit Ajax verwirklichen will muss trickreich mit so genannten long live HTTP GET Requests spielen (siehe diese Google Wave Präsentation, Minute 11:00). Doch Abhilfe naht: das HTML5 WebSocket Interface findet sich bereits in den erstsen Web-Browsers implementiert. Auch der neue Editor’s Draft der WebSocketAPI von gestern (15. April 2010) sieht vielversprechend aus.
Das WebSocket Interface erlaubt den Aufbau einer bestehenden, fullduplex Verbindung über das WebSocket Protokoll und lässt sich erstaunlich einfach mit JavaScript in die eigenen Webanwendungen implementieren. Es besitzt einen Constructor
WebSocket(url [, protocol])
mit den Parameter URL (String) und dem optionalen Parameter protocoll (String).
Das WebSocket Interface besitzt die folgenden Attribute:
readonly String URL
readonly unsigned short readyState
0 = Connecting
1 = Open
2 = Closing
3 = Closed
readonly unsigned long bufferedAmount
Das WebSocket Interface besitzt zudem die folgenden Funktionen:
boolean send(String data) void close()
Außerdem besitzt das Interface folgende Events:
onopen onmessage onerror onclose
Eine typische und rudimentäre Implementierung könnte demnach so aussehen:
var mySocket = new WebSocket('ws://domain.com:80');
mySocket.onopen = function() {
setInterval(function() {
mySocket.send('Hello');
}, 50);
}
Wir erstellen demnach ein WebSocket Objekt und senden alle 50ms eine Nachricht an den Empfänger auf Port 80. Hier können bereits Probleme auftreten: Was wenn die Verbindung des ausführenden Rechners nicht ausreicht um alle 50ms eine Nachricht zu versenden? Hierfür nehmen wir das Attribut bufferedAmount zur Hilfe. bufferedAmount ist nur dann gleich 0, wenn keine Daten mehr in der Warteschlange zum Versenden sind. Unsere überarbeitete Implementierung:
var mySocket = new WebSocket('ws://domain.com:80');
mySocket.onopen = function() {
setInterval(function() {
if(mySocket.bufferedAmount == 0) {
mySocket.send('Hello');
}
}, 50);
}
Empfangene Daten können wir mit dem onmessage Event verarbeiten:
mySocket.onmessage = function(data) {
document.getElementById('Output').appendChild(
document.createTextNode(data)
);
}
Hier zeigen wir die Daten im Browserfenster an. Fehler können wir mit dem error Event abfangen. Das Auslösen des error Events muss nicht zwangsläufig bedeuten, dass die Verbindung abgebrochen ist, kann es aber:
mySocket.onerror = function(error) {
alert('error');
if(mySocket.readyState != 1) {
document.getElementById('Output').appendChild(
document.createTextNode("Ein Fehler ist aufgetreten.")
);
}
}
Um Daten mit einem Server auszutauschen benötigen wir einen Server, der das WebSocket-Protokoll unterstützt. Für die ersten Experimente eignet sich zum Beispiel pywebsocket. Es kann sowohl als Apache-Modul oder auch als Stand-Alone-Server betrieben werden.
Im Moment unterstützen meines Wissens leider nur Google Chrome und Safari WebSocket. Firefox wird es in nicht alzu ferner Zukunft implementieren. Eine Chat-Demo unter Verwendung von WebSockets findet sich hier.
Anregungen? Hierfür sind die Kommentare da.