WebSocket

Z Wikipedii, wolnej encyklopedii
Przejdź do nawigacji Przejdź do wyszukiwania
WebSocket
Platforma sprzętowa wieloplatformowy
Rodzaj Protokół komunikacyjny
Licencja 2-klauzulowa licencja BSD
Strona internetowa

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.

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łana na portach 80 i 443 przypisanych do HTTP, a także 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[edytuj | edytuj kod]

WebSocket’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[edytuj | edytuj kod]

WebSocket 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].

Implementacja WebSocket w przeglądarkach internetowych
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 | edytuj kod]

// 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[edytuj | edytuj kod]

Aby 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ła 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ż[edytuj | edytuj kod]

Przypisy[edytuj | edytuj kod]

  1. I. Fette, A. Melnikov, The WebSocket Protocol, RFC 6455, IETF, grudzień 2011, DOI10.17487/RFC6455, ISSN 2070-1721, OCLC 943595667 (ang.).
  2. rfc6455, datatracker.ietf.org [dostęp 2021-07-28].
  3. Adobe Flash Platform * Sockets, help.adobe.com [dostęp 2021-07-28], Cytat: TCP connections require a “client” and a “server.” Flash Player can create client sockets. (ang.).
  4. WebSockets – Lista Web API | MDN, developer.mozilla.org [dostęp 2021-07-28] (ang.).
  5. Uniform Resource Identifier (URI) Schemes, www.iana.org [dostęp 2021-07-28] (ang.).
  6. Ian Fette, rfc6455, datatracker.ietf.org [dostęp 2021-07-28].
  7. 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.
  8. HTML 5, www.w3.org [dostęp 2021-07-28].
  9. [whatwg] TCPConnection feedback from Michael Carter on 2008-06-18 (whatwg@whatwg.org from June 2008), lists.w3.org [dostęp 2021-07-28] (ang.).
  10. IRC logs: freenode / #whatwg / 20080618, krijnhoetmer.nl [dostęp 2021-07-28] (ang.).
  11. Web Sockets Now Available In Google Chrome, Chromium Blog [dostęp 2021-07-28] (ang.).
  12. Wpis na blogu Firefoksa dotyczący zablokowania WebSocket.
  13. Wpis na blogu Opery dotyczący zablokowania WebSocket. [dostęp 2010-12-15]. [zarchiwizowane z tego adresu (2010-12-15)].
  14. Can I use Web Sockets, caniuse.com [dostęp 2017-11-15] (ang.).
  15. a b 640003 – WebSockets – upgrade to ietf-07, bugzilla.mozilla.org [dostęp 2021-07-28] (ang.).
  16. 64470 – chromium – An open-source project to help move the web forward. – Monorail, bugs.chromium.org [dostęp 2021-07-28].
  17. Opera Developer News – A hot Opera 12.50 summer-time snapshot, web.archive.org, 5 sierpnia 2012 [dostęp 2021-07-28] [zarchiwizowane z adresu 2012-08-05].
  18. rfc6455, datatracker.ietf.org [dostęp 2021-07-28] (ang.).
  19. FAQ – BiDirectional or Server-Initiated HTTP Wiki, 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.).
  20. Opening Handshake, [w:] Ian Fette, rfc6455, datatracker.ietf.org [dostęp 2021-07-28] (ang.).
  21. Base Framing Protocol, [w:] Ian Fette, rfc6455, datatracker.ietf.org [dostęp 2021-07-28] (ang.).
  22. John A. Tamplin, A Multiplexing Extension for WebSockets, datatracker.ietf.org [dostęp 2021-07-28] (ang.).