{"id":12162,"date":"2021-02-19T21:20:10","date_gmt":"2021-02-19T20:20:10","guid":{"rendered":"https:\/\/blog.mi.hdm-stuttgart.de\/?p=12162"},"modified":"2023-06-18T18:08:10","modified_gmt":"2023-06-18T16:08:10","slug":"websocket-protokoll-ein-detaillierter-technischer-einblick","status":"publish","type":"post","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2021\/02\/19\/websocket-protokoll-ein-detaillierter-technischer-einblick\/","title":{"rendered":"WebSocket-Protokoll: Ein detaillierter technischer Einblick"},"content":{"rendered":"<p><span style=\"font-family: Arial, sans-serif\">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 \u00fcbertragen [7]. Auch der Header selbst wurde auf Performance getrimmt. So wurde aus dem textuellen Format ein bin\u00e4r-Kodiertes. Zudem wurden neue Funktionen wie das Caching hinzugef\u00fcgt, um das Laden von Daten zu minimieren [7][8].<\/span><\/p>\n<p><span style=\"font-family: Arial, sans-serif\">Jedoch funktioniert das HTTP-Protokoll in seiner Grund-Funktionalit\u00e4t immer noch gleich. Es besteht immer noch aus einer Anfrage und einer Antwort und die Verbindung kann nicht beliebig lange offen gehalten werden.<\/span><\/p>\n<p><span style=\"font-family: Arial, sans-serif\">Es ist dem Server nicht m\u00f6glich, von sich aus Daten an den Client zu senden. Dieser Datenaustausch kann nur vom Client initiiert werden [7][8].<\/span><\/p>\n<p><span style=\"font-family: Arial, sans-serif\">Hier kn\u00fcpft das WebSocket-Protokoll [2] an. Es bietet eine bidirektionale Daten\u00fcbertragung, welche es dem Server erlaubt, direkt ohne Client-Anfrage Daten zu senden, was das Realisieren von Echtzeit-Web-Anwendungen ohne gro\u00dfe Netzlast oder Latenz erm\u00f6glicht. Zudem ist der Header sehr klein und einfach zu interpretieren. Dadurch ist das Protokoll sehr gut zum Senden vieler kleiner Nachrichten geeignet.<\/span><\/p>\n<p><span style=\"font-family: Arial, sans-serif\">Im Folgenden werden zun\u00e4chst allgemeine Informationen und wichtige Eigenschaften des WebSocket-Protokolls beschrieben und die Vorteile und Nachteile gegen\u00fcber 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\u00fcr die Client-seitige WebSocket-Implementierung vorgestellt und deren Funktionen mit dem internen Verhalten des Protokolls in Beziehung gesetzt.<\/span><\/p>\n\n\n<h2 class=\"wp-block-heading\">Allgemein<\/h2>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Das WebSocket-Protokoll ist ein seit 2011 existierendes Internet-Protokoll, welches auf der Anwendungsschicht des OSI-Modells angesiedelt ist und der bidirektionalen Daten-\u00dcbermittlung \u00fcber einer konstanten TCP-Verbindung dient. Dabei werden die Standard-HTTP-Ports mit verwendet, also 80 oder 8080 bei unverschl\u00fcsselten und 443 bei verschl\u00fcsselten Verbindungen. Dies hat den Vorteil, dass keine zus\u00e4tzlichen Firewall-Einstellungen n\u00f6tig sind, um das WebSocket-Protokoll zu ber\u00fccksichtigen [9]. Das WebSocket-Protokoll ist im RFC 6455 von der IETF (Internet Engineering Task Force) standardisiert und aktuell in der Version 13 verf\u00fcgbar [2]. Es dient prim\u00e4r der Echtzeit-Daten\u00fcbertragung bei Echtzeit-Web-Anwendungen.<\/span><\/p>\n\n\n<h3 class=\"wp-block-heading\">Protokoll-Eigenschaften<\/h3>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Im Folgenden werden wichtige Eigenschaften des WebSocket-Protokolls genannt und die daraus entstehenden Einschr\u00e4nkungen und Vorteile gegen\u00fcber dem HTTP-Protokoll beschrieben.<\/span><\/p>\n\n\n<h4 class=\"wp-block-heading\">\u00dcbertragung gro\u00dfer Daten<\/h4>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Wie beim HTTP-Protokoll auch, k\u00f6nnen gr\u00f6\u00dfere Daten, welche nicht auf einmal in einen Puffer passen, wie zum Beispiel gr\u00f6\u00dfere Dateien, St\u00fcck f\u00fcr St\u00fcck versendet werden. Hierbei ist aber keine Fragmentierung auf Anwender-Schicht notwendig. Die Nachricht wird als eine gro\u00dfe Nachricht mit einem Header und gro\u00dfer Payload interpretiert, welche je nach Puffer-Gr\u00f6\u00dfe St\u00fcck f\u00fcr St\u00fcck eingelesen wird. Anhand der im Header gegebenen Payload-Gr\u00f6\u00dfe und der bisher empfangenen Payload-Daten kann ermittelt werden, ob noch Daten fehlen oder die Nachricht vollst\u00e4ndig ist [10].<\/span><\/p>\n<p><span style=\"font-family: Arial, sans-serif\">In Abbildung 1 ist die entsprechende Nachricht und der verf\u00fcgbare Puffer veranschaulicht.<\/span><\/p>\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/data_transfer-1.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"378\" height=\"151\" data-attachment-id=\"12165\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2021\/02\/19\/websocket-protokoll-ein-detaillierter-technischer-einblick\/data_transfer-1\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/data_transfer-1.jpg\" data-orig-size=\"378,151\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"data_transfer-1\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/data_transfer-1.jpg\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/data_transfer-1.jpg\" alt=\"Senden gro\u00dfer Daten durch St\u00fcck-weises einlesen in den Puffer\" class=\"wp-image-12165\" title=\"\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/data_transfer-1.jpg 378w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/data_transfer-1-300x120.jpg 300w\" sizes=\"auto, (max-width: 378px) 100vw, 378px\" \/><\/a><figcaption>Abbildung 1: Senden gro\u00dfer Daten durch St\u00fcck-weises einlesen in den Puffer<\/figcaption><\/figure>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Da dieses Verfahren von beiden Protokollen unterst\u00fctzt wird, existieren hier weder Vor- noch Nachteile.<\/span><\/p>\n\n\n<h4 class=\"wp-block-heading\">Verbindungsorientiert + konstante Verbindung + kleiner Header<\/h4>\n\n\n<p>Das WebSocket-Protokoll ist verbindungsorientiert [2]. Dies bedeutet, dass zun\u00e4chst eine HTTP-Anfrage und eine entsprechende Antwort geschickt werden muss, bevor die eigentlichen Daten versendet werden k\u00f6nnen [7]. Dies erzeugt zun\u00e4chst einen Mehraufwand in Form von Verarbeitungs-Aufwand und der Gr\u00f6\u00dfe an Daten, welche gesendet werden m\u00fcssen. Sollten jedoch mehrere Daten \u00fcber eine konstante Verbindung ohne erneuten Verbindungsaufbau gesendet werden, kann das WebSocket-Protokoll seine St\u00e4rke ausspielen. Der Header des WebSocket-Protokolls ist deutlich kleiner als der des HTTP-Protokolls, auch wenn der HTTP-Header bin\u00e4r 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 \u00fcbermittelnden Nachrichten einen gro\u00dfen Vorteil bringt. Da bereits das HTTP\/1.1-Protokoll mit Multiplexing-Funktionalit\u00e4r ausgestattet ist [7], kann der entscheidene Vorteil darin gesehen werden, dass das WebSocket-Protokoll eine konstante Verbindung besitzt, sodass die zu \u00fcbertragenden Daten nicht zu Beginn der \u00dcbertragung bekannt sein m\u00fcssen, was bei HTTP-Multiplexing aber der Fall ist, da die HTTP-Verbindung wieder geschlossen werden muss.<\/p>\n<p>Die folgende Formel gibt an, ab welcher Nachrichten-Anzahl sich der Einsatz von WebSockets lohnt, wenn f\u00fcr HTTP Multiplexing verwendet werden kann. Mit \u2018WS-Header\u2018 oder \u2018HTTP-Header\u2018 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\u00fcr das HTTP-Protokoll an. \u2018n\u2018 entspricht der Anzahl an Nachrichten [10].<\/p>\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">2 HTTP-Header + n WS-Header + 2 WS-Header &lt; n*2 HTTP-Header<\/code><\/pre>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Die zus\u00e4tzlichen 2 WS-Header entsprechen dem Verbindungs-Abbau.<\/span><\/p>\n\n\n<h4 class=\"wp-block-heading\">Maskierung<\/h4>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Da beim Hochladen von Daten die Payload maskiert werden muss [2], entsteht beim WebSocket-Protokoll ein Mehraufwand. Je gr\u00f6\u00dfer die Payload einer Nachricht ist, desto mehr muss maskiert werden, was die Gesamt-\u00dcbertragungszeit reduziert. Daher sollten beim Hochladen von Daten, der Payload-Anteil m\u00f6glichst gering gehalten werden.<\/span><\/p>\n\n\n<h4 class=\"wp-block-heading\">Bidirektional vs. Polling<\/h4>\n\n\n\n<p>Bidirektional bedeutet, dass zu einer beliebigen Zeit einer der Teilnehmer eine Nachricht an die Gegenstelle senden kann. Dadurch ist es dem Server m\u00f6glich, 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\u00f6glichst schnell Zustands-Aktualisierungen mitteilen muss. Anwendungs-Gebiete sind hierbei Echtzeit-Anwendungen wie Browser-Spiele [5], in welchen der Spieler m\u00f6glichst schnell vom Server informiert werden muss, wenn zum Beispiel ein neuer Gegner in sein Sichtfeld ger\u00e4t. Mit Hilfe des WebSocket-Protokolls kann der Server daher direkt eine Nachricht senden, was der Latenz einer Daten-\u00dcbertragung f\u00fcr eine Strecke entspricht.<\/p>\n\n\n\n<p>Die selbe Funktionalit\u00e4t mit dem HTTP-Protokoll muss mit Hilfe von Polling implementiert werden [6]. Dabei wird regelm\u00e4\u00dfig eine Anfrage gesendet, um den aktuellen Server-Zustand abzufragen. Dabei verursacht das permanente Abfragen eine gro\u00dfe Netzlast, was beim WebSocket-Protokoll nicht der Fall ist. Dar\u00fcber hinaus ist die Latenz meist deutlich h\u00f6her und abh\u00e4ngig von der Abfrage-Frequenz des Clients.<\/p>\n\n\n\n<p>In Abbildung 2 und 3 wird die Eigenschaft der Bidirektionalit\u00e4t und das Polling-Verfahren visuell veranschaulicht.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/full_duplex.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"378\" height=\"189\" data-attachment-id=\"12166\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2021\/02\/19\/websocket-protokoll-ein-detaillierter-technischer-einblick\/full_duplex\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/full_duplex.jpg\" data-orig-size=\"378,189\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"full_duplex\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/full_duplex.jpg\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/full_duplex.jpg\" alt=\"Server-Mitteilung mit bidirektionaler Daten\u00fcbertragung.\" class=\"wp-image-12166\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/full_duplex.jpg 378w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/full_duplex-300x150.jpg 300w\" sizes=\"auto, (max-width: 378px) 100vw, 378px\" \/><\/a><figcaption>Abbildung 2: Server-Mitteilung mit bidirektionaler Daten\u00fcbertragung<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/polling.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"378\" height=\"189\" data-attachment-id=\"12167\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2021\/02\/19\/websocket-protokoll-ein-detaillierter-technischer-einblick\/polling\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/polling.jpg\" data-orig-size=\"378,189\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"polling\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/polling.jpg\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/polling.jpg\" alt=\"\" class=\"wp-image-12167\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/polling.jpg 378w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/polling-300x150.jpg 300w\" sizes=\"auto, (max-width: 378px) 100vw, 378px\" \/><\/a><figcaption>Abbildung 3: Server-Mitteilung mit Polling-Verfahren<\/figcaption><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Keine Same-Origin-Policy<\/h4>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Das WebSocket-Protokoll folgt im Gegensatz zum HTTP-Protokoll keiner Same-Origin-Policy [1]. Es k\u00f6nnen also mehrere Verbindungen mit unterschiedlichen Dom\u00e4nen existieren. Um Sicherheitsprobleme wie Cross-Site-Scripting zu umgehen, muss der Server beim Verbindungsaufbau den mitgelieferten Origin-Header mit der eigenen Dom\u00e4ne abgleichen und eventuell die Verbindung trennen, wenn die Dom\u00e4ne der Client-Anwendung keine Valide ist.<\/span><\/p>\n\n\n<h3 class=\"wp-block-heading\">Anwendungsgebiete<\/h3>\n\n\n\n<p>Anwendungsgebiete f\u00fcr das WebSocket-Protokoll sind alle Anwendungen, welche m\u00f6glichst alle Eigenschaften und deren Einschr\u00e4nkungen des Protokolls optimal nutzen k\u00f6nnen. Prim\u00e4r 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\u00f6glich mitteilen, wenn sich der Spiel-Zustand insofern \u00e4ndert, dass es den entsprechenden Spieler betrifft. Aber auch beim Monitoring kann das WebSocket-Protokoll bestm\u00f6glich eingesetzt werden, da auch hier ein schneller bidirektionaler Datenverkehr zwischen Server und Client ben\u00f6tigt wird. Zudem kann durch das Verbinden mit verschiedener Dom\u00e4nen, der Zustand mehrerer Server eines gr\u00f6\u00dferen Netzwerks visualisiert werden [10].<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Verbindungsaufbau<\/h2>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Der Verbindungsaufbau des WebSocket-Protokolls entspricht einem klassischen HTTP-Zyklus bestehend aus Anfrage und Antwort. Im Folgenden sind die Minimal-Header f\u00fcr Anfrage und Antwort gegeben [1].<\/span><\/p>\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>HTTP-Anfrage<\/td><td>HTTP-Antwort<\/td><\/tr><tr><td>GET \/&lt;URL&gt; HTTP\/1.1<br>Upgrade: websocket<br>Connection: Upgrade<br>Sec-WebSocket-Key: &lt;String-In&gt;<br>Sec-WebSocket-Version: &lt;Version-in&gt;<\/td><td>HTTP\/1.1 101 Switching Protocols<br>Upgrade: websocket<br>Connection: Upgrade<br>Sec-WebSocket-Accept: &lt;String-Out&gt;<br>Sec-WebSocket-Version: &lt;Version-out&gt;<\/td><\/tr><\/tbody><\/table><figcaption>Tabelle 1: Minimaler Anfrage\/- und Antwort-HTTP-Header f\u00fcr WebSocket-Verbindungsaufbau [1]<\/figcaption><\/figure>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Die zu \u00fcbergebende &lt;URL&gt; kann beliebig gew\u00e4hlt werden, da diese f\u00fcr das WebSocket-Protokoll keine Bedeutung hat. Typischerweise wird die &lt;URL&gt; daher zur Differenzierung verschiedener WebSocket-Anwendungen, welche parallel auf dem Server laufen, verwendet [1].<\/span><\/p>\n<p><span style=\"font-family: Arial, sans-serif\">Um dem Server mitzuteilen, dass auf das WebSocket-Protokoll gewechselt werden soll, m\u00fcssen die Header \u2018Upgrade\u2018 und \u2018Connection\u2018 verwendet werden.<\/span><\/p>\n<p><span style=\"font-family: Arial, sans-serif\">Im \u2018Sec-WebSocket-Version\u2018-Header wird die vom Client unterst\u00fctzte WebSocket-Version &lt;Version-in&gt; angegeben. Meistens entspricht dies der aktuellen Version 13 [10].<\/span><\/p>\n<p><span style=\"font-family: Arial, sans-serif\">Vor dem Senden einer WebSocket-Nachricht muss der Client sicher stellen, dass der kontaktierte Server das WebSocket-Protokoll auch versteht. Andernfalls best\u00fcnde die Gefahr, dass der Server f\u00e4lschlicherweise eine WebSocket-Nachricht als HTTP-Nachricht interpretiert, was zu einer Sicherheitsl\u00fccke f\u00fchrt. Aus diesem Grund muss ein Base64-kodierter String &lt;String-in&gt;, welcher beliebig gew\u00e4hlt werden kann, im \u2018Sec-WebSocket-Key\u2018-Header mitgeliefert werden. Der Server muss diesen entsprechend der in Tabelle 2 angegebenen Schritte konvertieren und das Ergebnis in seiner Antwort im \u2018Sec-WebSocket-Accept\u2018-Header zur\u00fcck senden [1].<\/span><\/p>\n<p><span style=\"font-family: Arial, sans-serif\">Zus\u00e4tzlich kann der Server eine WebSocket-Version &lt;Version-out&gt; angeben, falls diese von der Angabe des Clients &lt;Version-in&gt; abweicht.<\/span><\/p>\n<p><span style=\"font-family: Arial, sans-serif\">Konnte keine Vereinbarung bez\u00fcglich der Version oder des Wechsels auf das WebSocket-Protokoll getroffen werden oder der zur\u00fcck gelieferte String &lt;String-out&gt; falsch sein, wird der Verbindungsaufbau abgebrochen [1].<\/span><\/p>\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Beschreibung<\/th><th>Beispiel<\/th><th>L\u00e4nge (Byte)<\/th><\/tr><\/thead><tbody><tr><td>&lt;String-In&gt;: beliebiger Base64-String<\/td><td>MQBbM45rKkPH\/ocIaDfOjw==<\/td><td>24<\/td><\/tr><tr><td>Konkatinierung mit statischem String<\/td><td>MQBbM45rKkPH\/ocIaDfOjw==258EAFA5-E914-47DA-95CA-C5AB0DC85B11<\/td><td>60<\/td><\/tr><tr><td>sha1-Hash<\/td><td>2e9a036975af28d8828712ff45a733eb4d9c2f53<\/td><td>40<\/td><\/tr><tr><td>Hex -&gt; Int<\/td><td>&lt;nicht darstellbar&gt;<\/td><td>20<\/td><\/tr><tr><td>base64: &lt;String-Out&gt;<\/td><td>LpoDaXWvKNiChxL\/Racz602cL1M=<\/td><td>28<\/td><\/tr><\/tbody><\/table><figcaption>Tabelle 2: Sec-WebSocket-Key-Konvertierung [1] [10]<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">WebSocket-Header<\/h2>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Der WebSocket-Header ist bin\u00e4r kodiert und in seiner Gr\u00f6\u00dfe variabel. Er kann je nach Payload-Gr\u00f6\u00dfe und \u00dcbertragungs-Richtung bis zu 14 Byte umfassen und eine minimale Gr\u00f6\u00dfe von 2 Byte betragen [1][2], was im Gegensatz zum HTTP-Header, auch wenn dieser bin\u00e4r kodiert sein sollte, deutlich kleiner ist. In Abbildung 4 ist der WebSocket-Header mit seinen Bestandteilen dargestellt. Im Folgenden werden diese detailliert beschrieben.<\/span><\/p>\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/websocket-header.png\"><img loading=\"lazy\" decoding=\"async\" width=\"632\" height=\"408\" data-attachment-id=\"12168\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2021\/02\/19\/websocket-protokoll-ein-detaillierter-technischer-einblick\/websocket-header\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/websocket-header.png\" data-orig-size=\"632,408\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"websocket-header\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/websocket-header.png\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/websocket-header.png\" alt=\"\" class=\"wp-image-12168\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/websocket-header.png 632w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/01\/websocket-header-300x194.png 300w\" sizes=\"auto, (max-width: 632px) 100vw, 632px\" \/><\/a><figcaption>Abbildung 4: WebSocket-Header [1]<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Opcode<\/h3>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Der Opcode, auch Operation-Code genannt, gibt den Typ der Nachricht an [2]. Aktuell sind folgende sechs Nachrichten-Typen definiert:<\/span><\/p>\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Code<\/th><th>Beschreibung<\/th><\/tr><\/thead><tbody><tr><td>0x0<\/td><td>Continuation (Kontroll-Rahmen)<\/td><\/tr><tr><td>0x1<\/td><td>Text (Payload-Typ: UTF-8-Text)<\/td><\/tr><tr><td>0x2<\/td><td>Binary (Payload-Typ: Bin\u00e4r-Format)<\/td><\/tr><tr><td>0x3-0x7<\/td><td>not used<\/td><\/tr><tr><td>0x8<\/td><td>Close (Kontroll-Rahmen)<\/td><\/tr><tr><td>0x9<\/td><td>Ping (Kontroll-Rahmen)<\/td><\/tr><tr><td>0xa<\/td><td>Pong (Kontroll-Rahmen)<\/td><\/tr><tr><td>0xb-0xf<\/td><td>not used<\/td><\/tr><\/tbody><\/table><figcaption>Tabelle 3: verf\u00fcgbare Opcodes des WebSocket-Header<\/figcaption><\/figure>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Die Opcodes \u2018Text\u2018 und \u2018Binary\u2018 geben an, dass in der Payload Anwendungs-bezogene Daten enthalten sind. Bei \u2018Text\u2018 muss die Payload als UTF-8-String, bei \u2018Binary\u2018 als Bin\u00e4r-Daten interpretiert werden. Die restlichen vier Kontroll-Rahmen werden in nachfolgenden Kapiteln mit Ihrem jeweiligen Verwendungszweck beschrieben.<\/span><\/p>\n\n\n<h3 class=\"wp-block-heading\">Fin &#8211; Fragmentierung auf Anwendungsschicht<\/h3>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Das Fin-Flag wird im Zusammenhang mit dem Opcode \u2018Continuation\u2018 verwendet, um Fragmentierung auf Applikations-Schicht zu erm\u00f6glichen. 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 \u2018Text\u2018 oder \u2018Binary\u2018 gesetzt. Der Daten-Typ ist dabei f\u00fcr alle Fragmente einer Gesamt-Nachricht der Selbe. Alle nachfolgenden Fragmente m\u00fcssen mit Opcode \u2018Continuation\u2018 gekennzeichnet werden [1][2].<\/span><\/p>\n<p><span style=\"font-family: Arial, sans-serif\">In Tabelle 4 ist das Zusammenspiel zwischen Opcode und Fin-Flag bei fragmentierter und nicht-fragmentierter Nachricht veranschaulicht. Aus [1] inspiriert.<br \/><\/span><\/p>\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>Fin<\/strong><\/td><td><strong>Opcode<\/strong><\/td><td><strong>Beschreibung<\/strong><\/td><\/tr><tr><td>1<\/td><td>1,2<\/td><td>Nachricht nicht fragmentiert.<\/td><\/tr><tr><td>0<\/td><td>1,2<\/td><td>Nachricht mit Typ 1,2 beginnt.<br>=&gt; weitere Nachrichten folgen, um Payload zu vervollst\u00e4ndigen.<\/td><\/tr><tr><td>0<\/td><td>0<\/td><td>Weiterer Teil der Nachricht mit Typ 1,2.<\/td><\/tr><tr><td>1<\/td><td>0<\/td><td>Letzter Teil der Nachricht.<br>=&gt; Payload jetzt vollst\u00e4ndig.<\/td><\/tr><\/tbody><\/table><figcaption>Tabelle 4: Zusammenspiel zwischen Opcode und Fin-Flag bei fragmentierter und nicht-fragmentierter Nachricht.<\/figcaption><\/figure>\n<\/div>\n<\/div>\n<\/div><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Mask<\/h3>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Wenn das Mask-Flag gesetzt ist, ist die Nachricht gemasked. Dies bedeutet, dass die Payload der Nachricht mit dem mitgelieferten 4-Byte gro\u00dfen Mask-Key XOR-Verschl\u00fcsselt wurde. Das Ver\/- und Entschl\u00fcsselungs-Verfahren ist dabei das Selbe und im Folgenden mit Programm-Code beschrieben, welcher von [1] inspiriert wurde:<\/span><\/p>\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">for (unsigned int i = 0; i &lt; payloadSize; ++i) {\n     pBuffer&#091;i] = pPayload&#091;i] ^ pMaskKey&#091;i % 4];\n}<\/code><\/pre>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">&#8216;pBuffer&#8217; enth\u00e4lt hierbei nach dem Verfahren entweder die verschl\u00fcsselte oder entschl\u00fcsselte Version der Payload, jenachdem, ob die Payload &#8216;pPayload&#8217; ver\/- oder entschl\u00fcsselt vorliegt.<\/span><\/p>\n<p><span style=\"font-family: Arial, sans-serif\">Wichtig ist hierbei, dass nur Nachrichten vom Client zum Server gemasked werden m\u00fcssen. Nachrichten vom Server zum Client d\u00fcrfen nicht gemasked werden [2].<\/span><\/p>\n<p><span style=\"font-family: Arial, sans-serif\">Sollte eine unverschl\u00fcsselte Nachricht dem Server oder eine Verschl\u00fcsselte dem Client gesendet werden, muss der Empf\u00e4nger die Verbindung schlie\u00dfen [1].<\/span><\/p>\n\n\n<h3 class=\"wp-block-heading\">Payload-Gr\u00f6\u00dfe<\/h3>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Die Anzahl der ben\u00f6tigten Bytes f\u00fcr die Kodierung der Payload-Gr\u00f6\u00dfe ist je nach Payload-Gr\u00f6\u00dfe unterschiedlich. Um die Gr\u00f6\u00dfe der Payload zu ermitteln m\u00fcssen zun\u00e4chst die 7 Bit des \u2018Payload-Len\u2019-Feldes interpretiert werden. Sollte dieser Wert kleiner als 126 sein, so entspricht dies der Payload-Gr\u00f6\u00dfe. Sollte der Wert aber 126 oder 127 sein, so m\u00fcssen weitere Bytes eingelesen werden und deren Wert als Payload-Gr\u00f6\u00dfe interpretiert werden. Bei 126 sind es 2 Byte, bei 127 8 Byte, die zus\u00e4tzlich eingelesen werden m\u00fcssen [1]. Dadurch m\u00fcssen bei kleineren Nachrichten unn\u00f6tige Bytes nicht mitgesendet werden, da sich die Anzahl der zur Kodierung der Payload-Gr\u00f6\u00dfe ben\u00f6tigten Bytes von der Nachrichten-Gr\u00f6\u00dfe abh\u00e4ngt.<\/span><\/p>\n\n\n<h3 class=\"wp-block-heading\">RSV<\/h3>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">RSV steht f\u00fcr \u2018Reserved\u2018 und stellt bisher ungenutzte Bits im Header dar, welche f\u00fcr eventuell sp\u00e4tere Protokoll-Erweiterungen in der Spezifikation reserviert sind.<\/span><\/p>\n\n\n<h2 class=\"wp-block-heading\">Verbindungsabbau<\/h2>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Um eine WebSocket-Verbindung zu schlie\u00dfen, kann einer der Teilnehmer zu jeder Zeit eine Nachricht mit dem Opcode \u2018Close\u2018 senden. Die Gegenstelle muss dann eine entsprechende Close-Nachricht zur\u00fcck senden. Die Payload der Close-Nachricht ist in zwei Abschnitte eingeteilt, welche zusammen nicht gr\u00f6\u00dfer als 125 Byte sein d\u00fcrfen. Hierbei entsprechen die ersten 2 Byte dem Close-Code, einer ID zur exakten Bestimmung des Schlie\u00df-Grunds. Alle nachfolgenden Bytes enthalten, wenn vorhanden, eine textuelle Beschreibung des Close-Codes [1]. Meistens wird jedoch nur der Close-Code gesendet [10].<br \/><\/span><\/p>\n<p><span style=\"font-family: Arial, sans-serif\">Nach dem Senden oder Empfangen einer Close-Nachricht d\u00fcrfen keine weiteren Nachrichten gesendet und empfangene Nachrichten nicht mehr ber\u00fccksichtigt werden [1].<\/span><\/p>\n\n\n<h2 class=\"wp-block-heading\">Zus\u00e4tzliche Funktionen<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Pings und Pongs<\/h3>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Sollte die Gegenstelle auf Anwender-Schicht nicht mehr erreichbar sein, so k\u00f6nnen Ressourcen gespart werden, wenn die Verbindung getrennt wird. Um zu erkennen, ob ein anderer Teilnehmer noch erreichbar ist, oder nicht, k\u00f6nnen zu einem beliebigen Zeitpunkt, Nachrichten mit dem Opcode \u2018Ping\u2018 gesendet werden. Die Payload kann hierbei beliebig gew\u00e4hlt werden, darf aber die Maximal-Gr\u00f6\u00dfe von 125 nicht \u00fcberschreiten. Durch den Empfang einer entsprechenden Ping-Nachricht ist der Empf\u00e4nger dazu gezwungen, eine Nachricht mit dem Opcode \u2018Pong\u2018 zur\u00fcck zu senden. Dabei muss die Payload der Pong-Nachricht den Daten der Ping-Nachricht entsprechen [1].<\/span><\/p>\n<p>Wann genau eine Ping-Nachricht gesendet werden sollte, ist in der Spezifikation nicht definiert und daher der Anwendung \u00fcberlassen [2]. Die Anwendung k\u00f6nnte die vergangene Zeit seit der letzten angekommenen Nachricht von einem bestimmten Teilnehmer messen. Sollte diese einen bestimmten festgelegten Wert \u00fcberschreiten, k\u00f6nnte 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].<\/p>\n<p>Bisher konnte aber die Erfahrung gemacht werden, dass der &#8216;Firefox&#8217;-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\u00f6tig ist [10].<\/p>\n<p><span style=\"font-family: Arial, sans-serif\">Sollten mehrere Pings gesendet werden, gen\u00fcgt es, einen Pong als Antwort zu senden. Pong-Nachrichten ohne dazugeh\u00f6rige Ping-Nachricht werden ignoriert [1].<\/span><\/p>\n\n\n<h3 class=\"wp-block-heading\">Sub-Protokolle<\/h3>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Subprotokolle dienen der Kennzeichnung bez\u00fcglich 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 \u00fcber einen eigenen HTTP-Header w\u00e4hrend dem Verbindungs-Aufbau. \u00dcber den HTTP-Header \u2018Sec-WebSocket-Protocol\u2018 k\u00f6nnen ein oder mehrere Sub-Protokolle beim Server angefragt werden, zum Beispiel mehrere Versionen eines Parsers. Der Server sendet dann das erste passende Sub-Protokoll \u00fcber selbigen Header zur\u00fcck an den Client [1].<\/span><\/p>\n\n\n<h2 class=\"wp-block-heading\">JavaScript WebSocket-API<\/h2>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Im Folgenden werden die wichtigsten Funktionen der WebSocket-API f\u00fcr die Sprache JavaScript auf Client-Seite kurz erl\u00e4utert, und im Parallelen veranschaulicht, welche Funktionen zu welchen Aktionen intern im Browser f\u00fchren, bezogen auf das WebSocket-Protokoll.<\/span> Die daf\u00fcr n\u00f6tigen Informationen wurden aus [3] und [4] entnommen.<\/p>\n\n\n<h3 class=\"wp-block-heading\">Verbindungsaufbau<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">var ws = new WebSocket(&lt;URL&gt;, &lt;subProtocols&gt;);<\/code><\/pre>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Das Erzeugen eines WebSocket-Objekts entspricht dem WebSocket-Verbindungs-Aufbau. Der erste Parameter entspricht der &lt;URL&gt;, \u00fcber welche der Server und eine auf dem Server laufende WebSocket-Anwendung gew\u00e4hlt werden kann, zu der eine Verbindung aufgebaut werden soll. Zu Beachten gilt, dass das \u2018http:\/\/\u2018 oder \u2018https:\/\/\u2018 in typischen HTTP-URL\u2019s mit einem \u2018ws:\/\/\u2018 f\u00fcr &#8216;WebSocket&#8217; beziehungsweise einem \u2018wss:\/\/&#8217; f\u00fcr &#8216;WebSocket Secure\u2018 bei sicheren Verbindungen ersetzt werden muss.<\/span><\/p>\n<p><span style=\"font-family: Arial, sans-serif\">Der zweite Parameter ist optional und kann zur Angabe bestimmter Sub-Protokolle verwendet werden. Hierbei kann entweder ein String oder Array von Strings \u00fcbergeben werden.<\/span><\/p>\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">ws.onopen = ()=&gt;{};<\/code><\/pre>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Bei erfolgreichem Verbindungsaufbau wird der Anendungs-Code durch den onopen-Listener informiert.<\/span><\/p>\n\n\n<h3 class=\"wp-block-heading\">Senden<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">ws.send(&lt;Content&gt;);<\/code><\/pre>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Das Senden von Daten geschieht \u00fcber die send-Funktion des WebSocket-Objekts. Jenachdem, welche Objekte als Parameter \u00fcbergeben werden, wird der Obcode im WebSocket-Header gesetzt. Tabelle 5 stellt alle m\u00f6glichen Kombinationen zwischen \u00fcbergebenem Objekt und Opcode dar.<\/span><\/p>\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>&lt;Content&gt;<\/th><th>Opcode<\/th><\/tr><\/thead><tbody><tr><td>String<\/td><td>Text<\/td><\/tr><tr><td>ArrayBuffer \/ Blob<\/td><td>Binary<\/td><\/tr><\/tbody><\/table><figcaption>Tabelle 5: Mapping zwischen \u00fcbergebenem Parameter und Opcode<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Empfangen<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">ws.onmessage = ev=&gt;{ev.data;};\nws.binaryType = &lt;Type&gt;;<\/code><\/pre>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">F\u00fcr den Empfang von Daten, wird der onmessage-Listener ben\u00f6tigt, welcher informiert wird, sobald die Payload der Nachricht vollst\u00e4ndig vorliegt. Die f\u00fcr den Empfang zur Verf\u00fcgung stehenden Objekte sind die Selben wie f\u00fcr das Senden. Jedoch muss beim Empfang einer Nachricht mit Opcode \u2018Binary\u2018 zus\u00e4tzlich bestimmt werden, ob ein ArrayBuffer-Objekt oder ein Blob-Objekt empfangen werden soll, da beide jeweils Bin\u00e4r-Formate darstellen. Daf\u00fcr wird das Objekt-Feld \u2018binaryType\u2018 verwendet. Ein \u00dcberblick \u00fcber die m\u00f6glichen Werte und deren Beziehungen ist in Tabelle 6 gegeben. \u2018-\u2018 <\/span><span style=\"font-family: Arial, sans-serif\">bedeutet, dass der Wert <\/span><span style=\"font-family: Arial, sans-serif\">nicht ber\u00fccksichtigt <\/span><span style=\"font-family: Arial, sans-serif\">wird.<\/span><\/p>\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Opcode<\/th><th>binaryType<\/th><th>ev.data<\/th><\/tr><\/thead><tbody><tr><td>Text<\/td><td>&#8211;<\/td><td>String<\/td><\/tr><tr><td>Binary<\/td><td>&#8220;arraybuffer&#8221;<\/td><td>ArrayBuffer<\/td><\/tr><tr><td>Binary<\/td><td>&#8220;blob&#8221;<\/td><td>Blob<\/td><\/tr><\/tbody><\/table><figcaption>Tabelle 6: Abh\u00e4ngigkeiten zwischen Opcode, &lt;Type&gt; und ev.data<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Verbindungsabbau<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">ws.onclose = ev=&gt;{};\nws.close(&lt;Code&gt;, &lt;Msg&gt;);<\/code><\/pre>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">F\u00fcr 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\u00fcck gesendet werden. Dies wird vom Browser-Laufzeit-System \u00fcbernommen. Sowohl das Event-Objekt, als auch die Sende-Funktion besitzen die M\u00f6glichkeit, den Close-Code, sowie eine optionale textuelle Close-Nachricht zu empfangen beziehungsweise zu senden.<\/span><\/p>\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Payload-Bestandteil<\/th><th>Senden<\/th><th>Empfangen<\/th><\/tr><\/thead><tbody><tr><td>Close-Code<\/td><td>&lt;Code&gt;<\/td><td>ev.code<\/td><\/tr><tr><td>Close-Message<\/td><td>&lt;Msg&gt;<\/td><td>ev.reason<\/td><\/tr><\/tbody><\/table><figcaption>Tabelle 7: Komponenten zum Lesen und Schreiben der Close-Payload<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Fehlermeldung<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">ws.onerror = ()=&gt;{};<\/code><\/pre>\n\n\n<p><span style=\"font-family: Arial, sans-serif\">Sollte w\u00e4hrend der WebSocket-Kommunikation ein Fehler auftreten, kann dieser \u00fcber den \u2018onerror\u2018-Event-Listener mitgeteilt werden. Jedoch wird hier lediglich ein Event-Objekt \u00fcbergeben, welches keinerlei Informationen \u00fcber den Fehler enth\u00e4lt. Ein entsprechender Fehler-Code ist immer nur im Close-Code enthalten, da dar\u00fcber alles kommuniziert wird, was das Schlie\u00dfen der Verbindung bewirkt hat, also auch Fehler [11].<\/span><\/p>\n\n\n<h2 class=\"wp-block-heading\">Socket.io<\/h2>\n\n\n\n<p>&#8216;Socket.io&#8217; ist eine abstraktere JavaScript-Bibliothek f\u00fcr 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\u00e4t der darunterliegenden Technologien, im Hintergrund entweder auf HTTP mittels Polling oder auf das WebSocket-Protokoll zugegriffen. &#8216;Socket.io&#8217; bietet aber noch weitere  Funktionalit\u00e4ten wie zum Beispiel Echtzeit-Analysen [13].<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Quellen<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>[1] &#8220;Writing WebSocket servers.&#8221; <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/WebSockets_API\/Writing_WebSocket_servers\">https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/WebSockets_API\/Writing_WebSocket_servers<\/a> . Zugegriffen am: 2021-01-08.<\/li><li>[2] &#8220;WebSocket-Spezifikation.&#8221; <a href=\"https:\/\/tools.ietf.org\/html\/rfc6455\">https:\/\/tools.ietf.org\/html\/rfc6455<\/a> . Zugegriffen am: 2021-01-08.<\/li><li>[3] &#8220;Writing WebSocket client applications.&#8221; <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/WebSockets_API\/Writing_WebSocket_client_applications\">https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/WebSockets_API\/Writing_WebSocket_client_applications<\/a> . Zugegriffen am: 2021-01-08.<\/li><li>[4] &#8220;JavaScript Websocket-API.&#8221; <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/WebSocket\">https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/WebSocket<\/a> . Zugegriffen am: 2021-01-08.<\/li><li>[5] &#8220;Splixio.&#8221; <a href=\"https:\/\/splix.io\">https:\/\/splix.io<\/a> . Zugegriffen am: 2021-01-08.<\/li><li>[6] &#8220;Polling.&#8221; <a href=\"https:\/\/de.wikipedia.org\/wiki\/Polling_(Informatik)\">https:\/\/de.wikipedia.org\/wiki\/Polling_(Informatik)<\/a> . Zugegriffen am: 2021-01-08.<\/li><li>[7] &#8220;HTTP\/1.1-Spezifikation.&#8221; <a href=\"https:\/\/tools.ietf.org\/html\/rfc2616\">https:\/\/tools.ietf.org\/html\/rfc2616<\/a> . Zugegriffen am: 2021-01-08.<\/li><li>[8] &#8220;HTTP\/3.&#8221; <a href=\"https:\/\/quicwg.org\/base-drafts\/draft-ietf-quic-http.html\">https:\/\/quicwg.org\/base-drafts\/draft-ietf-quic-http.html<\/a> . Zugegriffen am: 2021-01-08.<\/li><li>[9] &#8220;WebSocket.&#8221; <a href=\"https:\/\/en.wikipedia.org\/wiki\/WebSocket\">https:\/\/en.wikipedia.org\/wiki\/WebSocket<\/a> . Zugegriffen am: 2021-01-08.<\/li><li>[10] eigene Leistung, durch Experimente heraus gefunden<\/li><li>[11] &#8220;How-To-Read-Error-Code.&#8221; <a href=\"https:\/\/stackoverflow.com\/questions\/18803971\/websocket-onerror-how-to-read-error-description\">https:\/\/stackoverflow.com\/questions\/18803971\/websocket-onerror-how-to-read-error-description<\/a> . Zugegriffen am: 2021-01-08.<\/li><li>[12] &#8220;Firefox.&#8221; <a href=\"https:\/\/www.mozilla.org\/de\/firefox\/\">https:\/\/www.mozilla.org\/de\/firefox\/<\/a>. Zugegriffen am: 2021-02-19.<\/li><li>[13] &#8220;Socket.io.&#8221; <a href=\"https:\/\/socket.io\/\">https:\/\/socket.io\/<\/a>. Zugegriffen am: 2021-02-19.<\/li><\/ul>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 \u00fcbertragen [7]. Auch der Header selbst wurde auf Performance getrimmt. So wurde aus dem textuellen Format ein bin\u00e4r-Kodiertes. Zudem [&hellip;]<\/p>\n","protected":false},"author":1013,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[649,262,21],"tags":[],"ppma_author":[837],"class_list":["post-12162","post","type-post","status-publish","format-standard","hentry","category-interactive-media","category-rich-media-systems","category-system-architecture"],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":23162,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2022\/03\/27\/slog-deterministische-datenbanksysteme-die-losung-fur-alle-probleme\/","url_meta":{"origin":12162,"position":0},"title":"SLOG &#8211; Deterministische Datenbanksysteme die L\u00f6sung f\u00fcr alle* Probleme?","author":"Julia Grimm","date":"27. March 2022","format":false,"excerpt":"*zumindest im Bereich georeplizierter Datenbanken Wir leben in einer globalisierten Welt, in welcher wir Anwendungen auf der ganzen Welt nutzen k\u00f6nnen. Egal wo wir gerade sind, k\u00f6nnen wir auf diese Programme und Daten zugreifen. Doch diese M\u00f6glichkeit stellt Softwaresysteme heutzutage vor gro\u00dfe Herausforderungen. Nutzer m\u00f6chten so schnell wie m\u00f6glich auf\u2026","rel":"","context":"In &quot;Databases&quot;","block_context":{"text":"Databases","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/scalable-systems\/databases\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2022\/03\/Network-Monitoring.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2022\/03\/Network-Monitoring.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2022\/03\/Network-Monitoring.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2022\/03\/Network-Monitoring.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2022\/03\/Network-Monitoring.jpg?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":12206,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2021\/02\/18\/quic-die-zukunft\/","url_meta":{"origin":12162,"position":1},"title":"QUIC &#8211; Die Zukunft?","author":"Max Merz","date":"18. February 2021","format":false,"excerpt":"QUIC soll als neuer Standard das weit verbreitete TCP-Protokoll abl\u00f6sen. Welche Neuerungen QUIC mitbringt, wo seine St\u00e4rken liegen und warum \u00fcberhaupt eine Weiterentwicklung von TCP ben\u00f6tigt wird, versuche ich in diesem Artikel zu beantworten. QUIC allgemein Um zu verstehen, was QUIC ist und was es verbessern m\u00f6chte, muss man zuerst\u2026","rel":"","context":"In &quot;Interactive Media&quot;","block_context":{"text":"Interactive Media","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/interactive-media\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/02\/ISO-OSI_Spaces.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/02\/ISO-OSI_Spaces.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/02\/ISO-OSI_Spaces.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/02\/ISO-OSI_Spaces.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/02\/ISO-OSI_Spaces.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/02\/ISO-OSI_Spaces.png?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":12711,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2021\/02\/28\/effiziente-last-abarbeitung\/","url_meta":{"origin":12162,"position":2},"title":"Effiziente Last-Abarbeitung","author":"Laurin Keim","date":"28. February 2021","format":false,"excerpt":"Geschrieben von Steffen K\u00f6hler und Laurin Keim. Einleitung Bei dem vorliegenden Block-Post handelt es sich um den Zusammenschrieb eines Studentenprojekts mit dem Motto \u201cLast effizient abarbeiten\u201d. In diesem wurden verschiedene Vorgehensweisen, Protokolle und in gewissem Ma\u00dfe auch Hardware-Architekturen erarbeitet und nachvollzogen. Dabei wurden teilweise eigene Vorgehensweisen erdacht und anschlie\u00dfend mit\u2026","rel":"","context":"In &quot;System Designs&quot;","block_context":{"text":"System Designs","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/system-designs\/"},"img":{"alt_text":"","src":"https:\/\/lh4.googleusercontent.com\/DdOQ4v8k_Ow6hgMbOceRaY6NArvaqhHf4A7w7VfSWjXE6R7FE1Wh6venqya80xwX-kFdYnqVU9RgBP1fOf4SGJlrsVbtP9clJGMlBpFyF86n4NMlFGB63CFT5tqbqNk3NA","width":350,"height":200,"srcset":"https:\/\/lh4.googleusercontent.com\/DdOQ4v8k_Ow6hgMbOceRaY6NArvaqhHf4A7w7VfSWjXE6R7FE1Wh6venqya80xwX-kFdYnqVU9RgBP1fOf4SGJlrsVbtP9clJGMlBpFyF86n4NMlFGB63CFT5tqbqNk3NA 1x, https:\/\/lh4.googleusercontent.com\/DdOQ4v8k_Ow6hgMbOceRaY6NArvaqhHf4A7w7VfSWjXE6R7FE1Wh6venqya80xwX-kFdYnqVU9RgBP1fOf4SGJlrsVbtP9clJGMlBpFyF86n4NMlFGB63CFT5tqbqNk3NA 1.5x"},"classes":[]},{"id":2610,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2017\/08\/24\/predictive-policing-eine-kritisch-negative-vorhersage\/","url_meta":{"origin":12162,"position":3},"title":"Predictive Policing \u2013 eine kritisch-negative Vorhersage","author":"Marc Schelling","date":"24. August 2017","format":false,"excerpt":"In diesem Blogpost m\u00f6chte ich auf die Gefahren, die Predictive Policing verursachen k\u00f6nnte, eingehen wenn es als wissenschaftlich fundiert angesehen und bedenkenlos eingesetzt wird. Predictive Policing bedeutet 'vorausschauende Polizeiarbeit' und ist nicht erst seit dem Zehn-Punkte-Plan von Martin Schulz und der SPD ein beliebtes Buzzword im Zusammenhang mit Wohnungseinbr\u00fcchen. Dabei\u2026","rel":"","context":"In &quot;Secure Systems&quot;","block_context":{"text":"Secure Systems","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/system-designs\/secure-systems\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":23781,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2023\/02\/01\/websockets-technischer-einblick-und-performance-vergleich\/","url_meta":{"origin":12162,"position":4},"title":"WebSockets: Technischer Einblick und Performance-Vergleich","author":"Nicole W\u00f6lfel","date":"1. February 2023","format":false,"excerpt":"In diesem Artikel wird ein kurzer Blick auf die zu Grunde liegende, technische Funktionsweise von WebSockets geworfen und ihre Performance im Vergleich zu HTTP und Server-sent Events (SSE) untersucht, wodurch letztlich das Potenzial von WebSockets eruiert werden kann. Hintergrund & Entstehung In der Vergangenheit war es bei Webanwendungen nur unter\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/01\/SSEvsWebSockets_neu.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/01\/SSEvsWebSockets_neu.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/01\/SSEvsWebSockets_neu.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/01\/SSEvsWebSockets_neu.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":24048,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2023\/03\/03\/cdns-und-die-dsgvo\/","url_meta":{"origin":12162,"position":5},"title":"CDNs und die DSGVO","author":"Yannick M\u00f6ller","date":"3. March 2023","format":false,"excerpt":"In Zeiten von weltweit verteilten gro\u00dfen Systemen im Internet und der \u00fcberwiegend mobilen Bedienung von Webseiten ist die schnelle Daten\u00fcbertragung an alle Orte auf der Welt ein entscheidendes Thema. Kein Deutscher Urlauber in Amerika m\u00f6chte eine Ewigkeit auf die hei\u00dfgeliebte online-Ausgabe der Bild-Zeitung l\u00e4nger als ein paar Sekunden warten. Und\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/03\/image-1.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/03\/image-1.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/03\/image-1.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/03\/image-1.png?resize=700%2C400&ssl=1 2x"},"classes":[]}],"jetpack_sharing_enabled":true,"authors":[{"term_id":837,"user_id":1013,"is_guest":0,"slug":"lk173","display_name":"Laurin Keim","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/60b6efc7d4ed4727f12ba72dc11998e5218fea7205564129792591e6a90dbc44?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/12162","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/users\/1013"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/comments?post=12162"}],"version-history":[{"count":20,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/12162\/revisions"}],"predecessor-version":[{"id":12311,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/12162\/revisions\/12311"}],"wp:attachment":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/media?parent=12162"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/categories?post=12162"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/tags?post=12162"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/ppma_author?post=12162"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}