, ,

WebSocket-Protokoll: Ein detaillierter technischer Einblick

Laurin Keim

Das HTTP-Protokoll existiert seit Beginn des Internets und hat sich bis heute in Bezug auf Performance immer weiter entwickelt. Die vielen TCP-Verbindungs-Aufbau-Prozeduren wurden durch das Multiplexing auf ein paar Wenige reduziert, welche jeweils mehrere verschiedene Daten übertragen [7]. Auch der Header selbst wurde auf Performance getrimmt. So wurde aus dem textuellen Format ein binär-Kodiertes. Zudem wurden neue Funktionen wie das Caching hinzugefügt, um das Laden von Daten zu minimieren [7][8].

Jedoch funktioniert das HTTP-Protokoll in seiner Grund-Funktionalität immer noch gleich. Es besteht immer noch aus einer Anfrage und einer Antwort und die Verbindung kann nicht beliebig lange offen gehalten werden.

Es ist dem Server nicht möglich, von sich aus Daten an den Client zu senden. Dieser Datenaustausch kann nur vom Client initiiert werden [7][8].

Hier knüpft das WebSocket-Protokoll [2] an. Es bietet eine bidirektionale Datenübertragung, welche es dem Server erlaubt, direkt ohne Client-Anfrage Daten zu senden, was das Realisieren von Echtzeit-Web-Anwendungen ohne große Netzlast oder Latenz ermöglicht. Zudem ist der Header sehr klein und einfach zu interpretieren. Dadurch ist das Protokoll sehr gut zum Senden vieler kleiner Nachrichten geeignet.

Im Folgenden werden zunächst allgemeine Informationen und wichtige Eigenschaften des WebSocket-Protokolls beschrieben und die Vorteile und Nachteile gegenüber dem HTTP-Protokoll offen gelegt. Daraufhin wird ein detaillierter technischer Einblick in die Implementierung und Funktionsweise des Protokolls gegeben. Am Schluss wird die JavaScript-WebSocket-API als Beispiel-API für die Client-seitige WebSocket-Implementierung vorgestellt und deren Funktionen mit dem internen Verhalten des Protokolls in Beziehung gesetzt.

Allgemein

Das WebSocket-Protokoll ist ein seit 2011 existierendes Internet-Protokoll, welches auf der Anwendungsschicht des OSI-Modells angesiedelt ist und der bidirektionalen Daten-Übermittlung über einer konstanten TCP-Verbindung dient. Dabei werden die Standard-HTTP-Ports mit verwendet, also 80 oder 8080 bei unverschlüsselten und 443 bei verschlüsselten Verbindungen. Dies hat den Vorteil, dass keine zusätzlichen Firewall-Einstellungen nötig sind, um das WebSocket-Protokoll zu berücksichtigen [9]. Das WebSocket-Protokoll ist im RFC 6455 von der IETF (Internet Engineering Task Force) standardisiert und aktuell in der Version 13 verfügbar [2]. Es dient primär der Echtzeit-Datenübertragung bei Echtzeit-Web-Anwendungen.

Protokoll-Eigenschaften

Im Folgenden werden wichtige Eigenschaften des WebSocket-Protokolls genannt und die daraus entstehenden Einschränkungen und Vorteile gegenüber dem HTTP-Protokoll beschrieben.

Übertragung großer Daten

Wie beim HTTP-Protokoll auch, können größere Daten, welche nicht auf einmal in einen Puffer passen, wie zum Beispiel größere Dateien, Stück für Stück versendet werden. Hierbei ist aber keine Fragmentierung auf Anwender-Schicht notwendig. Die Nachricht wird als eine große Nachricht mit einem Header und großer Payload interpretiert, welche je nach Puffer-Größe Stück für Stück eingelesen wird. Anhand der im Header gegebenen Payload-Größe und der bisher empfangenen Payload-Daten kann ermittelt werden, ob noch Daten fehlen oder die Nachricht vollständig ist [10].

In Abbildung 1 ist die entsprechende Nachricht und der verfügbare Puffer veranschaulicht.

Senden großer Daten durch Stück-weises einlesen in den Puffer
Abbildung 1: Senden großer Daten durch Stück-weises einlesen in den Puffer

Da dieses Verfahren von beiden Protokollen unterstützt wird, existieren hier weder Vor- noch Nachteile.

Verbindungsorientiert + konstante Verbindung + kleiner Header

Das WebSocket-Protokoll ist verbindungsorientiert [2]. Dies bedeutet, dass zunächst eine HTTP-Anfrage und eine entsprechende Antwort geschickt werden muss, bevor die eigentlichen Daten versendet werden können [7]. Dies erzeugt zunächst einen Mehraufwand in Form von Verarbeitungs-Aufwand und der Größe an Daten, welche gesendet werden müssen. Sollten jedoch mehrere Daten über eine konstante Verbindung ohne erneuten Verbindungsaufbau gesendet werden, kann das WebSocket-Protokoll seine Stärke ausspielen. Der Header des WebSocket-Protokolls ist deutlich kleiner als der des HTTP-Protokolls, auch wenn der HTTP-Header binär kodiert sein sollte. Zudem muss das HTTP-Protokoll pro Daten-Transfer zwei Header, eine Anfrage und eine Antwort, senden. Somit ist der Aufwand pro Nachricht beim WebSocket-Protokoll geringer, was bei vielen zu übermittelnden Nachrichten einen großen Vorteil bringt. Da bereits das HTTP/1.1-Protokoll mit Multiplexing-Funktionalitär ausgestattet ist [7], kann der entscheidene Vorteil darin gesehen werden, dass das WebSocket-Protokoll eine konstante Verbindung besitzt, sodass die zu übertragenden Daten nicht zu Beginn der Übertragung bekannt sein müssen, was bei HTTP-Multiplexing aber der Fall ist, da die HTTP-Verbindung wieder geschlossen werden muss.

Die folgende Formel gibt an, ab welcher Nachrichten-Anzahl sich der Einsatz von WebSockets lohnt, wenn für HTTP Multiplexing verwendet werden kann. Mit ‘WS-Header‘ oder ‘HTTP-Header‘ ist der Aufwand gemeint, welcher mit dem Versenden und Erstellen beziehungsweise Lesen des entsprechenden Headers einhergeht. Der linke Teil gibt den Aufwand des WebSocket-Protokolls, der rechte Teil den Aufwand für das HTTP-Protokoll an. ‘n‘ entspricht der Anzahl an Nachrichten [10].

2 HTTP-Header + n WS-Header + 2 WS-Header < n*2 HTTP-Header

Die zusätzlichen 2 WS-Header entsprechen dem Verbindungs-Abbau.

Maskierung

Da beim Hochladen von Daten die Payload maskiert werden muss [2], entsteht beim WebSocket-Protokoll ein Mehraufwand. Je größer die Payload einer Nachricht ist, desto mehr muss maskiert werden, was die Gesamt-Übertragungszeit reduziert. Daher sollten beim Hochladen von Daten, der Payload-Anteil möglichst gering gehalten werden.

Bidirektional vs. Polling

Bidirektional bedeutet, dass zu einer beliebigen Zeit einer der Teilnehmer eine Nachricht an die Gegenstelle senden kann. Dadurch ist es dem Server möglich, Nachrichten an den Client zu senden, ohne eine vorherige Anfrage erhalten zu haben. Dies ist vor allem in Anwendungsgebieten von Vorteil, in denen der Server dem Client möglichst schnell Zustands-Aktualisierungen mitteilen muss. Anwendungs-Gebiete sind hierbei Echtzeit-Anwendungen wie Browser-Spiele [5], in welchen der Spieler möglichst schnell vom Server informiert werden muss, wenn zum Beispiel ein neuer Gegner in sein Sichtfeld gerät. Mit Hilfe des WebSocket-Protokolls kann der Server daher direkt eine Nachricht senden, was der Latenz einer Daten-Übertragung für eine Strecke entspricht.

Die selbe Funktionalität mit dem HTTP-Protokoll muss mit Hilfe von Polling implementiert werden [6]. Dabei wird regelmäßig eine Anfrage gesendet, um den aktuellen Server-Zustand abzufragen. Dabei verursacht das permanente Abfragen eine große Netzlast, was beim WebSocket-Protokoll nicht der Fall ist. Darüber hinaus ist die Latenz meist deutlich höher und abhängig von der Abfrage-Frequenz des Clients.

In Abbildung 2 und 3 wird die Eigenschaft der Bidirektionalität und das Polling-Verfahren visuell veranschaulicht.

Server-Mitteilung mit bidirektionaler Datenübertragung.
Abbildung 2: Server-Mitteilung mit bidirektionaler Datenübertragung
Abbildung 3: Server-Mitteilung mit Polling-Verfahren

Keine Same-Origin-Policy

Das WebSocket-Protokoll folgt im Gegensatz zum HTTP-Protokoll keiner Same-Origin-Policy [1]. Es können also mehrere Verbindungen mit unterschiedlichen Domänen existieren. Um Sicherheitsprobleme wie Cross-Site-Scripting zu umgehen, muss der Server beim Verbindungsaufbau den mitgelieferten Origin-Header mit der eigenen Domäne abgleichen und eventuell die Verbindung trennen, wenn die Domäne der Client-Anwendung keine Valide ist.

Anwendungsgebiete

Anwendungsgebiete für das WebSocket-Protokoll sind alle Anwendungen, welche möglichst alle Eigenschaften und deren Einschränkungen des Protokolls optimal nutzen können. Primär wird das WebSocket-Protokoll in Echtzeit-Anwendungen wie Browser-Spielen [5], Chat-Anwendungen oder beim Streaming verwendet. Browser-Spiele tauschen viele kleine Nachrichten zwischen Server und Client aus. Zudem muss der Server dem Client schnellstmöglich mitteilen, wenn sich der Spiel-Zustand insofern ändert, dass es den entsprechenden Spieler betrifft. Aber auch beim Monitoring kann das WebSocket-Protokoll bestmöglich eingesetzt werden, da auch hier ein schneller bidirektionaler Datenverkehr zwischen Server und Client benötigt wird. Zudem kann durch das Verbinden mit verschiedener Domänen, der Zustand mehrerer Server eines größeren Netzwerks visualisiert werden [10].

Verbindungsaufbau

Der Verbindungsaufbau des WebSocket-Protokolls entspricht einem klassischen HTTP-Zyklus bestehend aus Anfrage und Antwort. Im Folgenden sind die Minimal-Header für Anfrage und Antwort gegeben [1].

HTTP-AnfrageHTTP-Antwort
GET /<URL> HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: <String-In>
Sec-WebSocket-Version: <Version-in>
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: <String-Out>
Sec-WebSocket-Version: <Version-out>
Tabelle 1: Minimaler Anfrage/- und Antwort-HTTP-Header für WebSocket-Verbindungsaufbau [1]

Die zu übergebende <URL> kann beliebig gewählt werden, da diese für das WebSocket-Protokoll keine Bedeutung hat. Typischerweise wird die <URL> daher zur Differenzierung verschiedener WebSocket-Anwendungen, welche parallel auf dem Server laufen, verwendet [1].

Um dem Server mitzuteilen, dass auf das WebSocket-Protokoll gewechselt werden soll, müssen die Header ‘Upgrade‘ und ‘Connection‘ verwendet werden.

Im ‘Sec-WebSocket-Version‘-Header wird die vom Client unterstützte WebSocket-Version <Version-in> angegeben. Meistens entspricht dies der aktuellen Version 13 [10].

Vor dem Senden einer WebSocket-Nachricht muss der Client sicher stellen, dass der kontaktierte Server das WebSocket-Protokoll auch versteht. Andernfalls bestünde die Gefahr, dass der Server fälschlicherweise eine WebSocket-Nachricht als HTTP-Nachricht interpretiert, was zu einer Sicherheitslücke führt. Aus diesem Grund muss ein Base64-kodierter String <String-in>, welcher beliebig gewählt werden kann, im ‘Sec-WebSocket-Key‘-Header mitgeliefert werden. Der Server muss diesen entsprechend der in Tabelle 2 angegebenen Schritte konvertieren und das Ergebnis in seiner Antwort im ‘Sec-WebSocket-Accept‘-Header zurück senden [1].

Zusätzlich kann der Server eine WebSocket-Version <Version-out> angeben, falls diese von der Angabe des Clients <Version-in> abweicht.

Konnte keine Vereinbarung bezüglich der Version oder des Wechsels auf das WebSocket-Protokoll getroffen werden oder der zurück gelieferte String <String-out> falsch sein, wird der Verbindungsaufbau abgebrochen [1].

BeschreibungBeispielLänge (Byte)
<String-In>: beliebiger Base64-StringMQBbM45rKkPH/ocIaDfOjw==24
Konkatinierung mit statischem StringMQBbM45rKkPH/ocIaDfOjw==258EAFA5-E914-47DA-95CA-C5AB0DC85B1160
sha1-Hash2e9a036975af28d8828712ff45a733eb4d9c2f5340
Hex -> Int<nicht darstellbar>20
base64: <String-Out>LpoDaXWvKNiChxL/Racz602cL1M=28
Tabelle 2: Sec-WebSocket-Key-Konvertierung [1] [10]

WebSocket-Header

Der WebSocket-Header ist binär kodiert und in seiner Größe variabel. Er kann je nach Payload-Größe und Übertragungs-Richtung bis zu 14 Byte umfassen und eine minimale Größe von 2 Byte betragen [1][2], was im Gegensatz zum HTTP-Header, auch wenn dieser binär kodiert sein sollte, deutlich kleiner ist. In Abbildung 4 ist der WebSocket-Header mit seinen Bestandteilen dargestellt. Im Folgenden werden diese detailliert beschrieben.

Abbildung 4: WebSocket-Header [1]

Opcode

Der Opcode, auch Operation-Code genannt, gibt den Typ der Nachricht an [2]. Aktuell sind folgende sechs Nachrichten-Typen definiert:

CodeBeschreibung
0x0Continuation (Kontroll-Rahmen)
0x1Text (Payload-Typ: UTF-8-Text)
0x2Binary (Payload-Typ: Binär-Format)
0x3-0x7not used
0x8Close (Kontroll-Rahmen)
0x9Ping (Kontroll-Rahmen)
0xaPong (Kontroll-Rahmen)
0xb-0xfnot used
Tabelle 3: verfügbare Opcodes des WebSocket-Header

Die Opcodes ‘Text‘ und ‘Binary‘ geben an, dass in der Payload Anwendungs-bezogene Daten enthalten sind. Bei ‘Text‘ muss die Payload als UTF-8-String, bei ‘Binary‘ als Binär-Daten interpretiert werden. Die restlichen vier Kontroll-Rahmen werden in nachfolgenden Kapiteln mit Ihrem jeweiligen Verwendungszweck beschrieben.

Fin – Fragmentierung auf Anwendungsschicht

Das Fin-Flag wird im Zusammenhang mit dem Opcode ‘Continuation‘ verwendet, um Fragmentierung auf Applikations-Schicht zu ermöglichen. Dabei wird das Fin-Bit nur gesetzt, wenn es sich bei der Nachricht um das letzte Fragment der Gesamt-Nachricht handelt. Der Opcode wird zu Beginn auf den Daten-Typ der Payload, also ‘Text‘ oder ‘Binary‘ gesetzt. Der Daten-Typ ist dabei für alle Fragmente einer Gesamt-Nachricht der Selbe. Alle nachfolgenden Fragmente müssen mit Opcode ‘Continuation‘ gekennzeichnet werden [1][2].

In Tabelle 4 ist das Zusammenspiel zwischen Opcode und Fin-Flag bei fragmentierter und nicht-fragmentierter Nachricht veranschaulicht. Aus [1] inspiriert.

FinOpcodeBeschreibung
11,2Nachricht nicht fragmentiert.
01,2Nachricht mit Typ 1,2 beginnt.
=> weitere Nachrichten folgen, um Payload zu vervollständigen.
00Weiterer Teil der Nachricht mit Typ 1,2.
10Letzter Teil der Nachricht.
=> Payload jetzt vollständig.
Tabelle 4: Zusammenspiel zwischen Opcode und Fin-Flag bei fragmentierter und nicht-fragmentierter Nachricht.

Mask

Wenn das Mask-Flag gesetzt ist, ist die Nachricht gemasked. Dies bedeutet, dass die Payload der Nachricht mit dem mitgelieferten 4-Byte großen Mask-Key XOR-Verschlüsselt wurde. Das Ver/- und Entschlüsselungs-Verfahren ist dabei das Selbe und im Folgenden mit Programm-Code beschrieben, welcher von [1] inspiriert wurde:

for (unsigned int i = 0; i < payloadSize; ++i) {
     pBuffer[i] = pPayload[i] ^ pMaskKey[i % 4];
}

‘pBuffer’ enthält hierbei nach dem Verfahren entweder die verschlüsselte oder entschlüsselte Version der Payload, jenachdem, ob die Payload ‘pPayload’ ver/- oder entschlüsselt vorliegt.

Wichtig ist hierbei, dass nur Nachrichten vom Client zum Server gemasked werden müssen. Nachrichten vom Server zum Client dürfen nicht gemasked werden [2].

Sollte eine unverschlüsselte Nachricht dem Server oder eine Verschlüsselte dem Client gesendet werden, muss der Empfänger die Verbindung schließen [1].

Payload-Größe

Die Anzahl der benötigten Bytes für die Kodierung der Payload-Größe ist je nach Payload-Größe unterschiedlich. Um die Größe der Payload zu ermitteln müssen zunächst die 7 Bit des ‘Payload-Len’-Feldes interpretiert werden. Sollte dieser Wert kleiner als 126 sein, so entspricht dies der Payload-Größe. Sollte der Wert aber 126 oder 127 sein, so müssen weitere Bytes eingelesen werden und deren Wert als Payload-Größe interpretiert werden. Bei 126 sind es 2 Byte, bei 127 8 Byte, die zusätzlich eingelesen werden müssen [1]. Dadurch müssen bei kleineren Nachrichten unnötige Bytes nicht mitgesendet werden, da sich die Anzahl der zur Kodierung der Payload-Größe benötigten Bytes von der Nachrichten-Größe abhängt.

RSV

RSV steht für ‘Reserved‘ und stellt bisher ungenutzte Bits im Header dar, welche für eventuell spätere Protokoll-Erweiterungen in der Spezifikation reserviert sind.

Verbindungsabbau

Um eine WebSocket-Verbindung zu schließen, kann einer der Teilnehmer zu jeder Zeit eine Nachricht mit dem Opcode ‘Close‘ senden. Die Gegenstelle muss dann eine entsprechende Close-Nachricht zurück senden. Die Payload der Close-Nachricht ist in zwei Abschnitte eingeteilt, welche zusammen nicht größer als 125 Byte sein dürfen. Hierbei entsprechen die ersten 2 Byte dem Close-Code, einer ID zur exakten Bestimmung des Schließ-Grunds. Alle nachfolgenden Bytes enthalten, wenn vorhanden, eine textuelle Beschreibung des Close-Codes [1]. Meistens wird jedoch nur der Close-Code gesendet [10].

Nach dem Senden oder Empfangen einer Close-Nachricht dürfen keine weiteren Nachrichten gesendet und empfangene Nachrichten nicht mehr berücksichtigt werden [1].

Zusätzliche Funktionen

Pings und Pongs

Sollte die Gegenstelle auf Anwender-Schicht nicht mehr erreichbar sein, so können Ressourcen gespart werden, wenn die Verbindung getrennt wird. Um zu erkennen, ob ein anderer Teilnehmer noch erreichbar ist, oder nicht, können zu einem beliebigen Zeitpunkt, Nachrichten mit dem Opcode ‘Ping‘ gesendet werden. Die Payload kann hierbei beliebig gewählt werden, darf aber die Maximal-Größe von 125 nicht überschreiten. Durch den Empfang einer entsprechenden Ping-Nachricht ist der Empfänger dazu gezwungen, eine Nachricht mit dem Opcode ‘Pong‘ zurück zu senden. Dabei muss die Payload der Pong-Nachricht den Daten der Ping-Nachricht entsprechen [1].

Wann genau eine Ping-Nachricht gesendet werden sollte, ist in der Spezifikation nicht definiert und daher der Anwendung überlassen [2]. Die Anwendung könnte die vergangene Zeit seit der letzten angekommenen Nachricht von einem bestimmten Teilnehmer messen. Sollte diese einen bestimmten festgelegten Wert überschreiten, könnte eine Ping-Nachricht gesendet werden. Auf die entsprechende Pong-Antwort kann nun wiederum eine bestimmte festgelegte Zeit gewartet werden. Sollte bis dahin keine Pong-Nachricht ankommen, kann die TCP-Verbindung geschlossen werden [10].

Bisher konnte aber die Erfahrung gemacht werden, dass der ‘Firefox’-Browser [12] keine Ping-Nachrichten an den selbst erstellten Server gesendet hat. Dies liegt eventuell daran, dass der Browser erkennt, dass der Server lokal erreichbar ist, was bedeutet, dass sich beide Teilnehmer auf der selben Maschine befinden wodurch das Senden einer Ping-Nachricht damit unnötig ist [10].

Sollten mehrere Pings gesendet werden, genügt es, einen Pong als Antwort zu senden. Pong-Nachrichten ohne dazugehörige Ping-Nachricht werden ignoriert [1].

Sub-Protokolle

Subprotokolle dienen der Kennzeichnung bezüglich der Kodierung einer Payload. Beinhaltet die Payload beispielsweise einen JSON-String, so kann durch ein Sub-Protokoll dem Server mitgeteilt werden, dass er einen JSON-Parser zum interpretieren der Payload verwenden soll. Die Mitteilung der Sub-Protokolle geschieht über einen eigenen HTTP-Header während dem Verbindungs-Aufbau. Über den HTTP-Header ‘Sec-WebSocket-Protocol‘ können ein oder mehrere Sub-Protokolle beim Server angefragt werden, zum Beispiel mehrere Versionen eines Parsers. Der Server sendet dann das erste passende Sub-Protokoll über selbigen Header zurück an den Client [1].

JavaScript WebSocket-API

Im Folgenden werden die wichtigsten Funktionen der WebSocket-API für die Sprache JavaScript auf Client-Seite kurz erläutert, und im Parallelen veranschaulicht, welche Funktionen zu welchen Aktionen intern im Browser führen, bezogen auf das WebSocket-Protokoll. Die dafür nötigen Informationen wurden aus [3] und [4] entnommen.

Verbindungsaufbau

var ws = new WebSocket(<URL>, <subProtocols>);

Das Erzeugen eines WebSocket-Objekts entspricht dem WebSocket-Verbindungs-Aufbau. Der erste Parameter entspricht der <URL>, über welche der Server und eine auf dem Server laufende WebSocket-Anwendung gewählt werden kann, zu der eine Verbindung aufgebaut werden soll. Zu Beachten gilt, dass das ‘http://‘ oder ‘https://‘ in typischen HTTP-URL’s mit einem ‘ws://‘ für ‘WebSocket’ beziehungsweise einem ‘wss://’ für ‘WebSocket Secure‘ bei sicheren Verbindungen ersetzt werden muss.

Der zweite Parameter ist optional und kann zur Angabe bestimmter Sub-Protokolle verwendet werden. Hierbei kann entweder ein String oder Array von Strings übergeben werden.

ws.onopen = ()=>{};

Bei erfolgreichem Verbindungsaufbau wird der Anendungs-Code durch den onopen-Listener informiert.

Senden

ws.send(<Content>);

Das Senden von Daten geschieht über die send-Funktion des WebSocket-Objekts. Jenachdem, welche Objekte als Parameter übergeben werden, wird der Obcode im WebSocket-Header gesetzt. Tabelle 5 stellt alle möglichen Kombinationen zwischen übergebenem Objekt und Opcode dar.

<Content>Opcode
StringText
ArrayBuffer / BlobBinary
Tabelle 5: Mapping zwischen übergebenem Parameter und Opcode

Empfangen

ws.onmessage = ev=>{ev.data;};
ws.binaryType = <Type>;

Für den Empfang von Daten, wird der onmessage-Listener benötigt, welcher informiert wird, sobald die Payload der Nachricht vollständig vorliegt. Die für den Empfang zur Verfügung stehenden Objekte sind die Selben wie für das Senden. Jedoch muss beim Empfang einer Nachricht mit Opcode ‘Binary‘ zusätzlich bestimmt werden, ob ein ArrayBuffer-Objekt oder ein Blob-Objekt empfangen werden soll, da beide jeweils Binär-Formate darstellen. Dafür wird das Objekt-Feld ‘binaryType‘ verwendet. Ein Überblick über die möglichen Werte und deren Beziehungen ist in Tabelle 6 gegeben. ‘-‘ bedeutet, dass der Wert nicht berücksichtigt wird.

OpcodebinaryTypeev.data
TextString
Binary“arraybuffer”ArrayBuffer
Binary“blob”Blob
Tabelle 6: Abhängigkeiten zwischen Opcode, <Type> und ev.data

Verbindungsabbau

ws.onclose = ev=>{};
ws.close(<Code>, <Msg>);

Für den Verbindungsabbau existieren zum Empfangen einer Close-Nachricht ein entsprechender Listener und zum Senden einer Close-Nachricht eine Sende-Funktion. Hierbei muss aber beim Empfang einer Close-Nachricht keine Close-Nachricht manuell zurück gesendet werden. Dies wird vom Browser-Laufzeit-System übernommen. Sowohl das Event-Objekt, als auch die Sende-Funktion besitzen die Möglichkeit, den Close-Code, sowie eine optionale textuelle Close-Nachricht zu empfangen beziehungsweise zu senden.

Payload-BestandteilSendenEmpfangen
Close-Code<Code>ev.code
Close-Message<Msg>ev.reason
Tabelle 7: Komponenten zum Lesen und Schreiben der Close-Payload

Fehlermeldung

ws.onerror = ()=>{};

Sollte während der WebSocket-Kommunikation ein Fehler auftreten, kann dieser über den ‘onerror‘-Event-Listener mitgeteilt werden. Jedoch wird hier lediglich ein Event-Objekt übergeben, welches keinerlei Informationen über den Fehler enthält. Ein entsprechender Fehler-Code ist immer nur im Close-Code enthalten, da darüber alles kommuniziert wird, was das Schließen der Verbindung bewirkt hat, also auch Fehler [11].

Socket.io

‘Socket.io’ ist eine abstraktere JavaScript-Bibliothek für Client- aber auch Server-seitige Echtzeit-Kommunikation mit einer einheitlichen Schnittstelle, welche die Verwendung und Einbindung von Echtzeit-Kommunikation in Web-Anwendungen erleichtern soll. Dabei wird je nach Kompatibilität der darunterliegenden Technologien, im Hintergrund entweder auf HTTP mittels Polling oder auf das WebSocket-Protokoll zugegriffen. ‘Socket.io’ bietet aber noch weitere Funktionalitäten wie zum Beispiel Echtzeit-Analysen [13].

Quellen


by

Laurin Keim

Tags:

Comments

Leave a Reply