WebSocket
WebSocket – jest protokołem komunikacyjnym, zapewniającym dwukierunkowy kanał wymiany danych poprzez pojedyncze połączenie TCP. Protokół WebSockets został ustandaryzowany przez IETF jako RFC 6455 w 2011 roku[1], a jego przeglądarkowe API podlega standaryzacji w W3C.
Platforma sprzętowa | wieloplatformowy |
---|---|
Rodzaj | Protokół komunikacyjny |
Licencja | 2-klauzulowa licencja BSD |
Strona internetowa |
WebSockets różni się od protokołu HTTP. Oba protokoły są zlokalizowane na 7 warstwie w modelu OSI i zależą od TCP na warstwie 4. Pomimo faktu, że są one różne, standard RFC 6455 mówi, że WebSocket został zaprojektowany do działania na portach 80 i 443 przypisanych do HTTP, a także ma wspierać funkcje proxy i pośredników (intermediaries). Aby osiągnąć kompatybilność z HTTP, handshake WebSocket’u wykorzystuje nagłówek HTTP Upgrade[2], aby przełączyć komunikację z protokołu HTTP na WebSockets.
Protokół WebSocket umożliwia interakcję między przeglądarką internetową (lub inną aplikacją kliencką), a serwerem sieciowym przy niższym obciążeniu niż alternatywne rozwiązania półdupleksowe, takie jak np. odpytywanie HTTP (polling), ułatwiając przy tym znacznie przesyłanie danych w czasie rzeczywistym do i z serwera. Jest to możliwe dzięki zapewnieniu znormalizowanego sposobu wysyłania przez serwer treści do klienta bez uprzedniego żądania klienta i umożliwienia przesyłania komunikatów tam i z powrotem przy zachowaniu aktywnego połączenia. W ten sposób między klientem, a serwerem może odbywać się dwukierunkowa wymiana danych. Komunikacja odbywa się zwykle przez port TCP o numerze 443 (lub 80 w przypadku połączeń niezabezpieczonych), co jest korzystne w środowiskach, które blokują połączenia dla aplikacji innych niż przeglądarki internetowe (np. klienty Torrent, IRC). Przed pojawieniem się WebSocket’ów podobną dwukierunkową komunikację przeglądarka-serwer osiągano w niestandardowy sposób, wykorzystując technologie takie jak Comet czy Adobe Flash Player[3].
Większość współczesnych przeglądarek obsługuje WebSocket’y, w tym m.in.: Google Chrome, Firefox, Microsoft Edge, Internet Explorer, Safari i Opera[4].
W przeciwieństwie do protokołu HTTP, WebSocket zapewnia komunikację w pełnym dupleksie. Dodatkowo WebSocket umożliwia przesyłanie wiadomości na wierzchu protokołu TCP. Sam protokół TCP obsługuje strumienie bajtów bez wbudowanej koncepcji wiadomości. Przed WebSocket komunikacja na porcie 80 w pełnym dupleksie była osiągalna przy użyciu kanałów Comet, jednak implementacja Comet nie jest trywialna, a ze względu na uzgadnianie TCP i obciążenie nagłówka HTTP jest nieefektywna w przypadku małych wiadomości. Protokół WebSocket ma na celu rozwiązanie tych problemów bez naruszania założeń bezpieczeństwa sieci.
Specyfikacja protokołu WebSocket definiuje ws
(WebSocket) i wss
(WebSocket Secure) jako dwa nowe schematy jednolitego identyfikatora zasobów (URI), które są używane odpowiednio do połączeń nieszyfrowanych i szyfrowanych[5]. Oprócz nazwy schematu i fragmentu (tj. # nie jest obsługiwany), pozostałe komponenty URI są zdefiniowane tak, aby używały ogólnej składni URI[6].
Wykorzystując narzędzia developera w przeglądarce, twórcy stron mogą sprawdzić zarówno handshake WebSocket’u, jak i poszczególne paczki (frames)[7].
Historia
edytujWebSocket’y zostały po raz pierwszy wymienione jako TCPConnection w bazowej specyfikacji HTML5, jako symbol zastępczy dla interfejsu (API) gniazda, opartego o protokół TCP[8]. W czerwcu 2008 roku Michael Carter przeprowadził serię dyskusji w wyniku których powstała pierwsza wersja protokołu znanego obecnie jako WebSocket[9].
Nazwa „WebSocket” została ukuta przez Iana Hicksona i Michaela Cartera podczas współpracy na kanale IRC #whatwg[10], a następnie włączona do specyfikacji HTML5 przez samego Hicksona. W grudniu 2009 r. Google Chrome 4 została pierwszą przeglądarką z pełną obsługą nowego standardu, z domyślnie włączonym API WebSocket[11]. Rozwój protokołu WebSocket został następnie przeniesiony z grup W3C i WHATWG do IETF w lutym 2010.
Po zakończeniu prac nad protokołem i jego domyślnym włączeniu w większości przeglądarek, standard RFC 6455 został sfinalizowany przez Iana Fettera w grudniu 2011 roku.
RFC 7692 wprowadził rozszerzenie kompresji wiadomości do WebSocket przy użyciu algorytmu DEFLATE.
Przeglądarki wspierające WebSocket
edytujWebSocket został zaimplementowany w przeglądarkach: Firefox 4, Google Chrome 4, Opera 11, Internet Explorer 10 oraz Safari 5 (również w mobilnym Safari dla iOS 4.2). Z powodu luk w zabezpieczeniach WebSocket został domyślnie wyłączony w Firefoksie 4 i Operze 11 do czasu ich naprawienia[12][13]. Aktualnie wszystkie najpopularniejsze przeglądarki wspierają tę technologię[14].
Protokół, wersja | Data konspektu | Internet Explorer | Firefox (PC) | Firefox (Android) | Chrome (PC, iOS, Android) | Safari (Mac, iOS) | Opera (PC, Android, iOS) | Android Browser |
---|---|---|---|---|---|---|---|---|
hixie-75 | 4 Luty, 2010 | 4 | 5.0.0 | |||||
hixie-76
hybi-00 |
6 Maj, 2010
23 Maj, 2010 |
4.0 (wyłączono) | 6 | 5.0.1 | 11.00 (wyłączono) | |||
hybi-07 | 22 kwietnia 2011 | 6[15] | ||||||
hybi-10 | 11 lipca 2011 | 7[15] | 7 | 14[16] | ||||
RFC 6455 | Grudzień 2011 | 10 | 11 | 11 | 16 | 6 | 12.10[17] | 4.4 |
Przykładowy klient w języku javaScript
edytuj// stworzenie nowego obiektu typu WebSocket
const socket = new WebSocket('ws://game.example.com:12010/updates');
// metoda wywoływana w momencie stworzenia socketu
socket.onopen = function () {
setInterval(function() {
if (socket.bufferedAmount == 0)
socket.send(getUpdateData());
}, 50);
};
// metoda wywoływana w momencie otrzymania wiadomości
socket.onmessage = function(event) {
handleUpdateData(event.data);
};
// metoda wywoływana w momencie zamknięcia gniazda
socket.onclose = function(event) {
onSocketClose(event);
};
// metoda wywoływana w momencie, gdy socket został zamknięty z powodu błędu
socket.onerror = function(event) {
onSocketError(event);
};
Handshake protokołu
edytujAby ustanowić połączenie typu WebSocket, klient musi najpierw wysłać żądanie typu handshake, dla którego serwer zwraca odpowiednią odpowiedź, jak pokazane jest to w przykładzie poniżej[18].
Zarówno w żądaniu klienta, jak i odpowiedzi serwera każda linia wiadomości kończy się znakiem nowej linii (\r\n
) – identycznie jak ma to miejsce w przypadku protokołu HTTP. Dodatkowo na samym końcu żądania/odpowiedzi musi znajdować się pusta linia.
Żądanie klienta:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
Odpowiedź serwera:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
Handshake rozpoczyna się od żądania/odpowiedzi HTTP, dzięki czemu dany serwer może obsługiwać połączenia HTTP, a także WebSocket na tym samym porcie. Po nawiązaniu połączenia komunikacja przełącza się na dwukierunkowy protokół binarny, który nie jest już zgodny z protokołem HTTP.
Oprócz nagłówka Upgrade
klient wysyła również nagłówek Sec-WebSocket-Key
zawierający losowe bajty zakodowane w standardzie base64, na co serwer odpowiada, podając hash tego klucza w nagłówku Sec-WebSocket-Accept
. Ma to na celu zapobieganie sytuacji, gdzie np. serwer/proxy buforujący wyśle ponownie całą zapisaną konwersację innemu klientowi, podczas gdy ten nie miał de facto styczności z właściwym serwerem[19]. Proces polega na tym, że funkcja szyfrująca dodaje stały ciąg znaków 258EAFA5-E914-47DA-95CA-C5AB0DC85B11
do wartości podanej w nagłówku Sec-WebSocket-Key
klienta (nie jest on dekodowany z base64), a następnie stosuje algorytm szyfrujący SHA-1, by na samym końcu zakodować uzyskaną wartość używając base64[20].
Gdy połączenie jest już ustanowione, klient i serwer mogą wysyłać sobie dane w formie binarnej lub tekstowej w postaci tzw. ramek w trybie pełnego dupleksu. Sama ramka ma niewielki narzut, dodając jedynie mały nagłówek, po którym znajdują się docelowe dane[21]. Transmisje WebSocket są opisywane jako „wiadomości”, w których pojedyncza wiadomość może być opcjonalnie podzielona na kilka ramek. Pozwala to na wysyłanie wiadomości, w których dostępne są dane początkowe, ale nie jest znana pełna długość wiadomości (wysyłane są jedna ramka danych za drugą, aż do osiągnięcia końca i zakończenia bitem FIN). Dzięki rozszerzeniom protokołu można to również wykorzystać do multipleksowania kilku strumieni jednocześnie (na przykład w celu uniknięcia monopolizowania użycia gniazda dla pojedynczego dużego ładunku)[22].
Zobacz też
edytujPrzypisy
edytuj- ↑ I. Fette , A. Melnikov , The WebSocket Protocol, RFC 6455, IETF, grudzień 2011, DOI: 10.17487/RFC6455, ISSN 2070-1721, OCLC 943595667 (ang.).
- ↑ rfc6455 [online], datatracker.ietf.org [dostęp 2021-07-28] .
- ↑ Adobe Flash Platform * Sockets [online], help.adobe.com [dostęp 2021-07-28], Cytat: TCP connections require a “client” and a “server.” Flash Player can create client sockets. (ang.).
- ↑ WebSockets – Lista Web API | MDN [online], developer.mozilla.org [dostęp 2021-07-28] (ang.).
- ↑ Uniform Resource Identifier (URI) Schemes [online], www.iana.org [dostęp 2021-07-28] (ang.).
- ↑ Ian Fette , rfc6455 [online], datatracker.ietf.org [dostęp 2021-07-28] .
- ↑ APPENDIX A: WebSocket Frame Inspection with Google Chrome Developer Tools, [w:] Vanessa Wang , The Definitive Guide to HTML5 WebSocket, Apress, ISBN 978-1-4302-4740-1 .
- ↑ HTML 5 [online], www.w3.org [dostęp 2021-07-28] .
- ↑ [whatwg] TCPConnection feedback from Michael Carter on 2008-06-18 (whatwg@whatwg.org from June 2008) [online], lists.w3.org [dostęp 2021-07-28] (ang.).
- ↑ IRC logs: freenode / #whatwg / 20080618 [online], krijnhoetmer.nl [dostęp 2021-07-28] (ang.).
- ↑ Web Sockets Now Available In Google Chrome [online], Chromium Blog [dostęp 2021-07-28] (ang.).
- ↑ Wpis na blogu Firefoksa dotyczący zablokowania WebSocket.
- ↑ Wpis na blogu Opery dotyczący zablokowania WebSocket. [dostęp 2010-12-15]. [zarchiwizowane z tego adresu (2010-12-15)].
- ↑ Can I use Web Sockets [online], caniuse.com [dostęp 2017-11-15] (ang.).
- ↑ a b 640003 – WebSockets – upgrade to ietf-07 [online], bugzilla.mozilla.org [dostęp 2021-07-28] (ang.).
- ↑ 64470 – chromium – An open-source project to help move the web forward. – Monorail [online], bugs.chromium.org [dostęp 2021-07-28] .
- ↑ Opera Developer News – A hot Opera 12.50 summer-time snapshot [online], web.archive.org, 5 sierpnia 2012 [dostęp 2021-07-28] [zarchiwizowane z adresu 2012-08-05] .
- ↑ rfc6455 [online], datatracker.ietf.org [dostęp 2021-07-28] (ang.).
- ↑ FAQ – BiDirectional or Server-Initiated HTTP Wiki [online], trac.ietf.org [dostęp 2021-07-28], Cytat: The computation [...] is meant to prevent a caching intermediary from providing a WS-client with a cached WS-server reply without actual interaction with the WS-server (ang.).
- ↑ Opening Handshake, [w:] Ian Fette , rfc6455, datatracker.ietf.org [dostęp 2021-07-28] (ang.).
- ↑ Base Framing Protocol, [w:] Ian Fette , rfc6455, datatracker.ietf.org [dostęp 2021-07-28] (ang.).
- ↑ John A. Tamplin , A Multiplexing Extension for WebSockets [online], datatracker.ietf.org [dostęp 2021-07-28] (ang.).