WebSockets in der Windows Consumer Preview

IEBlog Deutsch

Blog des Internet Explorer-Entwicklerteams

WebSockets in der Windows Consumer Preview

  • Comments 0

In der Windows 8 Consumer Preview und in Windows 8 Server Beta unterstützen IE10 und alle anderen Client- und Serverfunktionen von Microsoft WebSocket nun die endgültige Version des IETF WebSocket-Protokolls. Zusätzlich wird die „Candidate Recommendation“ WebSocket-API des W3C in IE10 umgesetzt.

WebSockets sind stabil und stehen Entwicklern zum Erstellen innovativer Anwendungen und Dienste zur Verfügung. Dieser Beitrag enthält eine einfache Einführung in die WebSocket-API des W3C und das zugrunde liegende WebSocket-Protokoll. Die aktualisierte Flipbook-Demo verwendet die aktuelle Version der API und des Protokolls.

In meinem letzten Beitrag habe ich WebSocket-Szenarien vorgestellt:

Mit WebSockets können von Webanwendungen Echtzeitbenachrichtigungen und Updates im Browser zur Verfügung gestellt werden. Entwickler mussten eine Möglichkeit finden, die Einschränkungen im ursprünglichen Modell der HTTP-Anforderungsantwort des Browsers, das nicht auf Echtzeitszenarien ausgerichtet war, zu umgehen. Mit WebSockets kann von Browsern ein bidirektionaler Vollduplex-Kommunikationskanal mit Diensten geöffnet werden. Dieser Kanal kann dann von beiden Seiten unmittelbar für den Datenaustausch verwendet werden. Websites von sozialen Netzwerken und Spielen bis hin zu Wirtschafts- und Finanzwebsites können nun bessere Echtzeitszenarien liefern, idealerweise, indem sie das gleiche Markup auf verschiedenen Browsern nutzen.

Seit der Veröffentlichung des Beitrags im September 2011 haben die Arbeitsgruppen erhebliche Fortschritte erzielt. Das WebSocket-Protokoll ist jetzt ein von der IETF vorgeschlagenes Standardprotokoll. Zusätzlich handelt es sich laut dem W3C bei der WebSocket-API um eine W3C-„Candidate Recommendation“.

Einführung in die WebSocket-API anhand eines Echo-Beispiels

Die Codeausschnitte im Folgenden verwenden einen einfachen Echo-Server, der mit dem System.Web.WebSockets-Namespace von ASP.NET erstellt wurde, um von der Anwendung gesendete Text- und Binärnachrichten wiederzugeben. Die Anwendung erlaubt es dem Benutzer, Text einzugeben, der gesendet und als Textnachricht zurückgegeben wird, oder ein Bild zu zeichnen, das gesendet und als binäre Nachricht zurückgegeben wird.

Screenshot einer Echo-Beispielanwendung für WebSockets.

Ein komplexeres Beispiel, das es Ihnen erlaubt, mit den Latenz- und Leistungsunterschieden zwischen WebSockets und HTTP-Abruf zu experimentieren, finden Sie in der Flipbook-Demo.

Ausführliche Informationen zum Herstellen einer Verbindung mit einem WebSocket-Server

Diese einfache Erklärung basiert auf einer direkten Verbindung zwischen der Anwendung und dem Server. Wenn ein Proxy konfiguriert ist, startet IE10 den Vorgang, indem dieser eine „HTTP CONNECT“-Anfrage an den Proxy sendet.

Sobald ein WebSocket-Objekt erstellt ist, erfolgt ein Handshake zwischen Client und Server, um eine WebSocket-Verbindung herzustellen.

Diagramm, das eine „HTTP GET Upgrade“-Anforderung von einem HTTP-Client an einen HTTP-Server darstellt.

Der Vorgang wird gestartet, indem IE10 eine HTTP-Anforderung an den Server sendet.

GET /echo HTTP/1.1

Host: example.microsoft.com

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==

Origin: http://microsoft.com

Sec-WebSocket-Version: 13

Sehen wir uns die einzelnen Teile dieser Anforderung genauer an.

Der Verbindungsvorgang beginnt mit einer standardmäßigen „HTTP GET“-Anforderung. Diese Anforderung kann Firewalls, Proxys und andere Zwischenstufen passieren.

GET /echo HTTP/1.1

Host: example.microsoft.com

Mit dem HTTP-Upgradeheader wird der Server aufgefordert, das Anwendungsschichtprotokoll von HTTP auf ein WebSocket-Protokoll umzuschalten.

Upgrade: websocket

Connection: Upgrade

In der Antwort transformiert der Server den Wert im „Sec-WebSocket-Key“-Header. Dadurch gibt der Server an, dass das WebSocket Protokoll verwendet werden kann:

Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==

Der „Origin“-Header wird von IE10 so festgelegt, dass der Server ursprungsbasierte Sicherheit erzwingen kann.

Origin: http://microsoft.com

Der „Sec-WebSocket-Version“-Header ermittelt die angeforderte Protokollversion. Version 13 ist die endgültige Version im vom IETF vorgeschlagenen Standard:

Sec-WebSocket-Version: 13

Wenn der Server die Anforderung akzeptiert, das Protokoll auf Anwendungsebene zu aktualisieren, sendet er eine HTTP 101 Switching Protocols-Antwort:

Diagramm, dass eine „HTTP 101 Switching Protocols“-Antwort von einem HTTP-Serverclient an einen HTTP-Client darstellt.

HTTP/1.1 101 Switching Protocols

Upgrade: websocket

Connection: Upgrade

Um anzugeben, dass das WebSocket-Protokoll verwendet werden kann, führt der Server eine Standardtransformation des „Sec-WebSocket-Keys“ der Clientanforderung aus und sendet die Ergebnisse im „Sec-WebSocket-Accept“-Header:

Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

IE10 vergleicht anschließend „Sec-WebSocket-Key“ und „Sec-WebSocket-Accept“, um zu überprüfen, ob es sich beim Server wirklich um einen WebSocket-Server handelt und keinen HTTP-Server.

Der Client-Handshake stellt eine HTTP-über-TCP-Verbindung zwischen IE10 und dem Server her. Nachdem der Server eine 101-Antwort zurückgesendet hat, schaltet das Anwendungsschichtprotokoll von HTTP auf WebSockets um, welches die vorher hergestellte TPC-Verbindung verwendet.

HTTP spielt zu diesem Zeitpunkt keine Rolle. Nachrichten könne nun mithilfe des WebSocket-Transferprotokolls jederzeit von jedem Endpunkt aus gesendet oder empfangen werden.

Diagramm, das das Versenden von WebSocket-Nachrichten zwischen zwei Web-Sockets darstellt.

Programmieren des Herstellens einer Verbindung mit einem WebSocket-Server

Im WebSocket-Protokoll werden zwei neue URI-Schemas definiert, die den HTTP-Schemas ähneln.

  • "ws:" "//" host [ ":" port ] path [ "?" query ] basiert auf dem „http:“-Schema. Der Standardport ist 80. Er wird für unsichere (unverschlüsselte) Verbindungen verwendet.
  • "wss:" "//" host [ ":" port ] path [ "?" query ] basiert auf dem „https:“-Schema. Der Standardport ist 443. Er wird für sichere Verbindungen verwendet, die über Transport Layer Security getunnelt werden.

Wenn Proxys oder Netzwerkzwischenstufen vorhanden sind, ist es wahrscheinlicher, dass sichere Verbindungen erfolgreich sind, da Zwischenstufen den sicheren Verkehr seltener transformieren.

Der folgende Codeausschnitt stellt eine WebSocket-Verbindung her:

var host = "ws://example.microsoft.com";

var socket = new WebSocket(host);

ReadyState – Ready … Set … Go …

Das „WebSocket.readyState“-Attribut gibt den Status der Verbindung an: „CONNECTING“, „OPEN“, „CLOSING“ oder „CLOSED“. Wenn WebSocket zum ersten Mal erstellt wird, wird der „readyState“ auf „CONNECTING“ festgelegt. Sobald die Verbindung hergestellt wurde, wird der „readyState“ auf „OPEN“ festgelegt. Wenn das Herstellen der Verbindung fehlschlägt, wird der „readyState“ auf „OPEN“ festgelegt.

Registrieren für „Open“-Ereignisse

Die Anwendung muss für „Open“-Ereignisse registriert werden, um Benachrichtigungen empfangen zu können, wenn die Verbindung hergestellt ist.

socket.onopen = function (openEvent) {

document.getElementById("serverStatus").innerHTML = 'Web Socket State::' + 'OPEN';

};

Die Vorgänge beim Senden und Empfangen von Nachrichten

Nach einem erfolgreichen Handshake können die Anwendung und der WebSocket-Server WebSocket-Nachrichten austauschen. Eine Nachricht besteht aus einer Folge von einem oder mehreren Nachrichtenfragmenten oder „Frames“ von Daten.

Jeder Frame enthält Informationen wie:

  • Länge des Frames
  • Nachrichtentyp (binär oder Text) im ersten Frame der Nachricht
  • Eine Kennzeichnung (FIN), die angibt, ob es sich um den letzten Frame der Nachricht handelt

Diagramm, dass den Inhalt von WebSocket-Frames darstellt.

IE10 setzt die Rahmen wieder zu vollständigen Nachrichten zusammen, bevor diese an das Skript weitergeleitet werden.

Programmieren des Sendens und Empfangens von Nachrichten

Die send -API ermöglicht Anwendungen das Senden von Nachrichten an den WebSocket-Server als UTF-8-Text, ArrayPuffers oder Blobs.

Beispielsweise wird mit diesem Abschnitt der vom Benutzer eingegebene Text abgerufen und als UFT-8-Textnachricht an den Server gesendet, der diese zurückgibt. Der Server prüft, ob der „readyState“ des WebSockets „OPEN“ lautet:

function sendTextMessage() {

if (socket.readyState != WebSocket.OPEN)

return;

 

var e = document.getElementById("textmessage");

socket.send(e.value);

}

Mit diesem Abschnitt wird das vom Benutzer gezeichnete Bild abgerufen und als Binärnachricht an den Server gesendet:

function sendBinaryMessage() {

if (socket.readyState != WebSocket.OPEN)

return;

 

var sourceCanvas = document.getElementById('source');

// msToBlob returns a blob object from a canvas image or drawing

socket.send(sourceCanvas.msToBlob());

// ...

}

Registrieren für „Message“-Ereignisse

Die Anwendung muss für „Message“-Ereignisse registriert werden, um Nachrichten empfangen zu können. Der Ereignishandler empfängt ein „MessageEvent“ mit den Daten in „MessageEvent.data.“. Daten können als Binär- oder Textnachrichten empfangen werden.

Bei Empfang einer Binärnachricht, steuert das „WebSocket.binaryType“-Attribut, ob die Nachrichtendaten als „Blob“- oder als „ArrayPuffer“-Datentyp zurückgegeben werden. Das Attribut kann entweder auf „blob“ oder auf „arraybuffer“ festgelegt werden.

Die folgenden Beispiele verwenden den Standardwert „blob“.

Dieser Ausschnitt empfängt das zurückgegebene Bild bzw. den zurückgegebenen Text vom WebSocket-Server. Wenn es sich bei den Daten um einen Blob handelt, wurde das Bild zurückgegeben und wird auf die Zielcanvas gezeichnet. Andernfalls wurde eine UTF-8-Textnachricht zurückgesendet und wird in einem Textfeld angezeigt.

socket.onmessage = function (messageEvent) {

if (messageEvent.data instanceof Blob) {

var destinationCanvas = document.getElementById('destination');

var destinationContext = destinationCanvas.getContext('2d');

var image = new Image();

image.onload = function () {

destinationContext.clearRect(0, 0, destinationCanvas.width, destinationCanvas.height);

destinationContext.drawImage(image, 0, 0);

}

image.src = URL.createObjectURL(messageEvent.data);

} else {

document.getElementById("textresponse").value = messageEvent.data;

}

};

Hinweise zum Schließen einer WebSocket-Verbindung

Wie beim Öffnen erfolgt auch beim Schießen ein Handshake. Beide Endpunkte (die Anwendung oder der Server) können diesen Handshake initiieren.

Eine spezielle Art von Frame – ein „Close“-Frame – wird an den anderen Endpunkt gesendet. Der „Close“-Frame kann einen optionalen Statuscode oder Grund für das Schließen enthalten. Das Protokoll legt eine Reihe von entsprechenden Werten für den Statuscode fest. Der Absender des „Close“-Frames darf nach dem „Close“-Frame keine weiteren Anwendungsdaten senden.

Wenn der andere Endpunkt einen „Close“-Frame empfängt, antwortet dieser ebenfalls mit einem „Close“-Frame. Ausstehende Nachrichten können noch vor der Antwort mit dem „Close“-Frame gesendet werden.

Diagramm, das eine Nachricht mit einem „Close“-Frame und die Antwort darstellt.

Programmieren des Schließens eines WebSockets und der Registrierung für „Close“-Ereignisse

Die Anwendung initiiert den „Close“-Handshake bei einer geöffneten Verbindung mithilfe der close -API:

socket.close(1000, "normal close");

Um Benachrichtigungen empfangen zu können, nachdem die Verbindung geschlossen wurde, muss die Anwendung für „Close“-Ereignisse registriert werden.

socket.onclose = function (closeEvent) {

document.getElementById("serverStatus").innerHTML = 'Web Socket State::' + 'CLOSED';

};

Die close -API akzeptiert zwei optionale Parameter: Einen Statuscode gemäß des Protokolls und eine Beschreibung. Der Statuscode muss entweder bei 1000 oder in einem Bereich von 3000 bis 4999 liegen. Beim Schließen wird das „readyState“ Attribut auf „CLOSING“ festgelegt. Nachdem IE10 die „Close“-Antwort vom Server erhalten hat, wird das „readyState“-Attribut auf „CLOSED“ festgelegt und ein „Close“-Ereignis ausgelöst.

Verwenden von Fiddler zum Anzeigen von WebSocket-Verkehr

Fiddler ist ein beliebter HTTP-Debugging-Proxy. Die aktuelle Version des WebSocket-Protokolls bietet eine bedingte Unterstützung. Sie können sich die Header, die beim WebSocket-Handshake ausgetauscht werden, genauer ansehen:

Screenshot von Fiddler mit einer WebSocket-Anfrage.

Alle WebSocket-Nachrichten werden auch protokolliert. Im folgenden Screenshot sehen Sie, dass „spiral“ als UTF-8-Textnachricht an den Server gesendet und zurückgegeben wurde.

Screenshot von Fiddler mit einer WebSocket-Antwort.

Weiterführende Informationen

Wenn Sie mehr über WebSockets erfahren möchten, können Sie sich diese Sitzungen von der Microsoft //Build/-Konferenz vom September 2011 ansehen:

Wenn Sie mehr über Microsoft-Technologien zum Erstellen eines WebSocket-Diensts erfahren möchten, stellen die folgenden Beiträge eine gute Einführung dar:

Beginnen Sie noch heute die Entwicklung mithilfe von WebSockets. Ich freue mich auf Ihr Feedback.

– Brian Raymor, Senior Program Manager, Windows Networking