Saturday 21 October 2017

Sec Websocket Protokół Binarne Opcje


W tym rozdziale chodzi o uaktualnienie do bardziej elastycznego HTML5 WebSocket Zaczynamy od krótkiego przeglądu istniejących już sieciowych sieci WWW, a następnie dowiesz się, dlaczego i jak z nich korzystać WebSocket. Zechciej pokazać, że protokół WebSocket ma dosłownie brak narzutu w porównaniu do Możesz rozważyć użycie WebSocket do opracowania następujących typów aplikacji. Live aukcje handlu powiadomienia sportowe. Live współpracować writing. Controlling sprzętu medycznego w sieci Web. Multiplayer gry online. Real-aktualizacje czasu w społecznych streams. For następnej wersji Zapisz aplikację Child, zamierzamy użyć WebSocket do wdrożenia warstwy komunikacyjnej aukcji online Celem jest umożliwienie osobom fizycznym i firmom zakupów ręcznie robionych dzieł sztuki i rzemiosła przez dzieci Wszelkie przychody trafią do celu Zapisz dziecko. Celem jest umożliwienie obejrzenia zalety zmiany protokołu komunikacji klient-serwer w sieci WWW Regularnie monitorujesz sieć WebSocket dzięki monitorowaniu sieci robić ruch z narzędziami Wireshark i Google Chrome Developer Tools. All funkcje po stronie serwera obsługujące ten rozdział jest napisany w Javie, używając Java API do implementacji referencji WebSocket, która jest częścią specyfikacji Java EE 7 Korzystamy z najnowszych zwolnienie serwera aplikacji GlassFish Jeśli nie znasz Javy, traktuj tę konfigurację po stronie serwera jako usługa obsługująca protokół WebSocket Dla programistów Java zainteresowanych nurkowaniem po stronie serwera dostarczamy kod źródłowy i krótkie komentarze jako część próbek kodu pochodzących z tej książki. Pokazujemy i porównujemy push-push danych po stronie serwera z wydarzeniami wysyłanymi przez serwer i WebSocket. Ponadto zobaczysz krótki przegląd wybranych ram, takich jak Portal i Atmosphere, które mogą usprawnić aplikację WebSocket rozwoju. Korzystanie z aplikacji Near Real-Time Applications. Protokół ten jest językiem lingua franca dzisiejszych aplikacji sieciowych, w których komunikacja między klientami i serwerami jest oparta na prośbie-respo nse paradygmat Na niskim poziomie przeglądarki internetowe ustanawiają połączenie TCP IP dla każdej sesji Obecnie istnieją trzy podstawowe opcje, które programiści używają do przeglądania stron internetowych, długiego odpytywania i transmisji strumieniowej Te opcje to haki na pół dupleksie jednokierunkowy protokół ulicy do symulacji zachowań w czasie rzeczywistym W czasie rzeczywistym rozumiemy zdolność do reagowania na zdarzenie, tak jak to się dzieje Omówmy każdy z nich. Odpytywanie kodu klienta wysyła żądania do serwera na podstawie wstępnie skonfigurowanego przedziału dla Przykładowo, używając funkcji setInterval JavaScript Niektóre odpowiedzi serwera są puste, jeśli żądane dane nie są jeszcze gotowe, jak pokazano na stronie Polling Na przykład, jeśli prowadzisz aukcję online i wyślij żądanie, aby zobaczyć zaktualizowane stawki, nie otrzymałeś żadnych danych, chyba że ktoś postawił nową ofertę. Zobacz, co dziecko siedzi na tylnym siedzeniu swojego samochodu i pyta co minutę, Czy przyjechaliśmy jeszcze I grzecznie odpowiadasz, jeszcze nie Jest to podobne do n pusta odpowiedź serwera Nie ma cennego obciążenia dla tego dzieciaka, ale nadal otrzymuje niektóre odpytywanie metadanych może powodować otrzymanie nagłówków odpowiedzi pełnych bez obciążenia danych, nie mówiąc już o rozpraszaniu kierowcy, że serwer wykonuje inne obowiązki..Long Polling. Long pollling Długie pobieranie rozpoczyna się podobnie do odpytywania klienta wysyła żądanie do serwera Ale w tym przypadku zamiast wysyłania pustej odpowiedzi serwer oczekuje na udostępnienie danych dla klienta Jeśli wymagane informacje są nie jest dostępny w określonym przedziale czasu, serwer wysyła pustą odpowiedź do klienta, zamyka i ponownie nawiązuje połączenie. Będziemy dać jeszcze jedną analogię do porównania odpytywania i długiego wybierania Wyobraź sobie imprezę na najwyższym piętrze budynku wyposażonego w inteligentna winda, która trwa co minutę i otwiera drzwi na wypadek, gdy jeden z gości chce zejść, by palić papierosa. Jeśli nikt nie wejdzie do windy, idzie na ziemię iw ciągu 60 sekund wzrasta Ponownie jest to scenariusz odpytywania Ale jeśli ta winda podeszła i czekała, aż ktoś zdecyduje się zejść na dół lub zmęczyć się na czekanie, możemy to nazwać długim trybem odpytywania. z punktu widzenia perspektywy jest to uzasadnione, że długi tryb odpytywania może wydawać się tak, jakbyśmy mieli do czynienia z serwerem powolnie reagującym. Dlatego technika ta jest również określana jako Hanging GET. Jeśli widzisz aukcję online, która zmienia ceny automatycznie, gdy ludzie licytują przedmioty, wygląda tak, jakby serwer przesyła dane do ciebie Ale są szanse, że ta funkcjonalność została zaimplementowana przez długie odpytywanie, które nie jest prawdziwym pushem po stronie serwera, ale jego emulacją. figura 2 długie odpytywanie. Strumienie Streamingu. Podczas strumieniowania przesyłania strumieniowego klient wysyła żądanie danych Gdy tylko serwer pobiera dane, rozpocznie przesyłanie strumieniowe dodając coraz więcej danych do obiektu odpowiedzi bez zamykania połączeń Serwer przesyła dane do klienta, udając że odpowiedź nigdy się nie skończy Na przykład zażądanie filmu z YouTube skutkuje transmisją strumieniową ramki danych po klatce bez zamykania połączenia. Rysferowanie strumieniowe 3.Polling i streaming mogą być używane jako pomijanie starszych przeglądarek, które nie obsługują serwera API HTML5 - sent zdarzeń i WebSocket. Implementowanie zdarzeń wysłanych przez serwer. Nieber przed nurkowaniem w protokole WebSocket zapoznaj się ze znormalizowanym sposobem implementowania zdarzeń wysyłanych przez serwer SSE Konsorcjum World Wide Web W3C opublikowało interfejs API dla przeglądarek internetowych, subskrybowanie zdarzeń wysłanych przez serwer Wszystkie nowoczesne przeglądarki obsługują obiekt EventSource, który może obsługiwać zdarzenia przybierające postać zdarzeń DOM Nie jest to żądanie-respo nse, ale raczej jednokierunkowe naciśnięcie danych, od serwera do przeglądarki. Zapisywanie zdarzeń wysyłanych przez serwer informuje o tym, jak przeglądarka internetowa może subskrybować i słuchać zdarzeń wysyłanych przez serwer. Przykład 1 Subskrybowanie zdarzeń wysyłanych przez serwer. WebSocket handshake. Any communication network które korzystają z protokołu WebSocket rozpoczynają się od uścisku dłoni podczas otwierania Ta uścisk dłoni uaktualnia połączenie z protokołem WebSocket Jest to uaktualnienie do komunikacji opartej na wiadomościach Omawiamy wiadomości aka ramki w dalszej części tego rozdziału. Dlaczego warto uaktualnić zamiast uruchamiać TCP jako protokół w pierwszej kolejności Powodem jest to, że WebSocket działa na tych samych portach 80 i 443, co robią i jest ważną zaletą, że żądania przeglądarki są przekierowywane przez te same porty, ponieważ dowolne połączenia gniazdowe mogą nie być dozwolone przez zapory przedsiębiorstwa Ze względów bezpieczeństwa wiele sieci korporacyjnych umożliwia tylko niektóre wychodzące porty I porty są zazwyczaj umieszczane w tzw. białych listach. Wysoka wydajność Przeglądarka sieciowa. Ilya Grigorik O Reilly udostępnia więcej informacji na temat protokołu TCP i. Uaktualnienie protokołu jest inicjowane przez żądanie klienta, który również wysyła klucz specjalny z żądaniem Serwer przetwarza to żądanie i wysyła potwierdzenie aktualizacji. połączenie WebSocket może być nawiązane tylko z punktem końcowym obsługującym WebSocket Poniżej przedstawiono uścisk dłoni na żądanie klienta. Ten klient wysyła żądanie GET dla uaktualnienia protokołu Sec-WebSocket-Key to tylko zestaw bajtów losowych serwer pobiera te bajty i dołącza do tego klucza specjalny globalnie unikatowy identyfikator GUID łańcucha 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 Następnie tworzy szablon SHA1 algorytmu Secure Hash i wykonuje kodowanie Base64 Wynikowy łańcuch bajtów musi być używany zarówno przez serwer, jak i klienta, a ten ciąg nie był używany przez punkty końcowe sieci, które nie rozumieją protokołu WebSocket. Następnie ta wartość jest kopiowana w Sec-Web Pole nagłówka akceptującego gniazda Serwer oblicza wartość i wysyła odpowiedź, potwierdzając uaktualnienie protokołu. Protokół WebSocket używa kodu błędu z błędem o zażądaniu 400, aby sygnalizować nieudaną aktualizację Uścisk dłoni może obejmować także żądanie podprotokołu i informacje o wersji serwera WebSocket, ale nie możesz podawać innych arbitralnych nagłówków Nie można przesyłać informacji o autoryzacji Są dwa sposoby na to Możesz albo przekazać informacje o autoryzacji jako pierwsze na przykład, unikatowy klientId może zostać przekazany jako część nagłówka żądania lub opakowania HTML lub umieść go w adresie URL jako parametr zapytania podczas początkowego uzgadniania Zobacz następujący przykład. Korzystanie z frameworów WebSocket. Praca z interfejsem WebSocket API wanilii wymaga przeprowadzenia dodatkowego kodu domowego na własną rękę Na przykład, jeśli przeglądarka klienta nie wsparcie WebSocket natywnie, musisz upewnić się, że Twój kod sprowadza się do spuścizny Dobra wiadomość jest taka, że ​​istnieją ramy, które pomogą Ci w tym zadaniu Takie ramy skrócą czas opracowywania, pozwalając na bardziej niż mniej kodu W tej sekcji zamieszczamy krótkie recenzje dwóch ram, które mogą usprawnić rozwój aplikacji internetowych w sieci WebSocket. Te ramy próbują wykorzystać najlepiej obsługiwany transport przez bieżąco przeglądarkę internetową i serwer, przy jednoczesnym oszczędzaniu dewelopera z wiedzy o internalsach używanego mechanizmu Programista może skoncentrować się na programowaniu logiki aplikacji, wywołując wywołania w ramach interfejsu API podczas przesyłania danych. Pozostałość zostanie wykonana przez ramy Portal jest biblioteką serwerowo-agnostyczną Bibliotekę ma na celu wykorzystanie protokołu WebSocket i dostarczenie ujednoliconego interfejsu API dla różnych transportów długiego odpytywania, przesyłania strumieniowego, WebSocket Obecnie, po podjęciu decyzji o użyciu WebSocket do kolejnego projektu, musisz pamiętaj o tych użytkowników, którzy nadal korzystają z wcześniejszych przeglądarek, takich jak Internet Explorer 9 lub starsze, które nie wspierają WebSocket In thi to Twoja aplikacja powinna z powodzeniem sprowadzić się do najlepszej alternatywy sieciowej Ręczne pisanie kodu w celu obsługi wszystkich możliwych przeglądarek i wersji wymaga dużo czasu, zwłaszcza w celu testowania i przechowywania kodu dla różnych platform Biblioteka Portal może pomóc, jak pokazano na przykładzie Proste asynchroniczny klient aplikacji internetowych z portalem. Example 4 Prosty asynchroniczny klient aplikacji internetowych z Portal. It sa formatem czytelnym dla człowieka. Większą przeglądarkę mają wbudowane czytniki i parsery XML. Jednostki XML mogą być sprawdzane pod kątem schematu XSD lub DTD. Schemat XML jest użyteczna cecha języka, ponieważ definiuje strukturę, treść i semantykę dokumentu XML Ze względu na swoją czytelność, schemat XML może być używany przez osoby, które nie są programistami i mogą być wykorzystane do integracji systemów zapisanych w różnych programach languages. Its są w następujący sposób. XML jest bardzo verbose Aby wysłać nazwę klienta, musisz coś takiego jak custname Mary custname. Weryfikacja XML na kliencie jest złożonym zadaniem W chwili obecnej nie istnieją żadne niezależne od platformy rozwiązania lub API do przeprowadzania sprawdzania poprawności programowo opartych na XSD lub DTD. XML w skrócie. Elliotte Rusty Harold i W Scott Means O Reilly dobrze napisana książka opisująca pełne spektrum funkcji i narzędzi XML. Jak wyjaśniono w usingajaxandjson JSON oznacza Notatnik Obiektu JavaScript i jest sposobem na reprezentowanie danych strukturalnych, które mogą być szyfrowane i dekodowane przez wszystkie przeglądarki internetowe JSON jest powszechnie akceptowane przez społeczność internetowa jako popularny sposób serializowania danych Jak wspomniano wcześniej, zapewnia bardziej kompaktowy sposób niż XML do reprezentowania danych, a wszystkie nowoczesne przeglądarki przeglądają i analizują dane JSON. Bufory protokołów Google. Bufor protokołu Google lub protobuf to ję zykowy i niezależny od platformy mechanizm rozszerzalny do szeregowania danych strukturalnych Po zdefiniowaniu, jak chcesz zorganizować dane, możesz użyć specjalnie wygenerowanego kodu źródłowego, aby łatwo napisać i czytać yo ur strukturyzowanych danych do iz różnych strumieni danych Programiści mogą korzystać z tych samych schematów w różnych środowiskach. developer musi określić, w jaki sposób szeregizowalna informacja musi być zorganizowana przez definiowanie typów komunikatów buforowych protokołów w plikach Każdy komunikat o buforze protokołu jest mały , logiczny zapis informacji zawierający parę par nazw wartości Ten plik protokołu buforowania protokołu jest językiem agnostycznym Narzędzie protokołu kompiluje pliki protokołu i produkuje artefakty specyficzne dla języka na przykład i pliki. Na przykład można utworzyć plik protokołu buforujący protokół dla pliku Zapisz Dziecko reprezentuje informacje o darczyńcach, jak pokazano w buforze protokołu dla wiadomości o przekazaniu. Przykład 5 Bufor protokołu dla wiadomości o przekazywaniu. Wszystkie wymagane kody dla deszylizacji serializacji - darowizny zostaną uwzględnione. Nie zamierzamy opublikować wygenerowanego kodu tutaj, ale możesz samodzielnie wygenerować ten kod z poprzedniej wiadomości. Zobacz dostępność kompilator protobuf dla Twojego preferowanego języka na stronie protobuf wiki Aby zapoznać się z technologią protobuf, sprawdź dokumentację i samouczki. Oto niektóre protobuf pros. Wiadomość jest zakodowana w kompaktowym i zoptymalizowanym formacie binarnym Informacje o formacie kodowania można znaleźć na stronie na stronie dokumentacji protokołu Buffers. Google obsługuje bufory protokołów dla szerokiego zakresu języków programowania języka Java, C, Python Społeczność deweloperska obsługuje ją też. Użycie buforów protokołów jest dobrze udokumentowane. Poniżej przedstawiono niektóre z wad. format nie jest czytelny dla człowieka. Chociaż protobuf jest kompaktowy, zwłaszcza gdy wiele wartości liczbowych jest przenoszonych przez algorytm kodowania, JSON jest natywnie obsługiwany przez JavaScript i nie wymaga żadnej dodatkowej implementacji parsera. Protobuf wymaga przeglądarek internetowych obsługujących format binarny, ale nie wszystkie z nich jeszcze nie są dostępne Możesz sprawdzić, które przeglądarki obsługują surowe dane binarne w Czy mogę używać. Używając WebSocket z Proxies. The Sam protokół sieci WebSocket nie jest świadomy pośredników, takich jak serwery proxy, zapory i filtry zawartości Serwery proxy są powszechnie używane do filtrowania treści, filtrowania zawartości i treści korporacyjnych. zawsze obsługiwał aktualizacje protokołów, ale wiele serwerów proxy najwyraźniej zignorowało tę część specyfikacji Do chwili, gdy WebSocket się pojawił, atrybut Upgrade nie był używany Problem z aplikacjami sieciowymi używającymi długotrwałego połączenia, takiego jak WebSocket, polega na tym, że serwery proxy mogą wybierz zamknięcie połączenia strumieniowego lub bezczynności połączenia sieci WebSocket, ponieważ próbują nawiązać połączenie z nieaktywnym serwerem Ponadto serwery proxy mogą buforować niezaszyfrowane odpowiedzi, zakładając, że przeglądarka musi otrzymywać odpowiedź w całości. Jeśli chcesz więcej informacji o tym, jak Aplikacja obsługująca technologię WebSocket musi obsługiwać serwery proxy, przejrzeć obszerny dokument badawczy firmy Peter Lubbers, serwerów WebSocket i serwerów proxy firmy Google. Autorami tej książki są NGINX niezwykle popularny równoważenie obciążenia oraz serwer proxy i serwer, aby służyć statycznym zasobom, obrazów i plików tekstowych, równoważy obciążenie między serwerami Javy i wykonuje wyładunek SSL, zmieniając żądania przeglądarek sieciowych w N GINX używa małych wątków, aby obsługiwać tysiące równoczesnych użytkowników, w przeciwieństwie do tradycyjnych serwerów sieciowych, które korzystają z jednego wątku roboczego na połączenie. Niedawno firma NGINX zaczęła obsługiwać protokół WebSocket. Dodanie aukcji, aby zapisać dziecko. Daliśmy wam wystarczająco dużo teorii zachęcamy do wdrożenia WebSocket w aplikacji "Zapisz dziecko". Celem jest stworzenie aukcji, dzięki której ludzie mogą licytować i kupować różne towary, a przychody pochodzą z zapisywania aukcji "Dziecko Auctions", wymagają komunikacji w czasie rzeczywistym, która jest zainteresowana konkretną pozycją aukcji musi być niezwłocznie powiadomiony o nadpłaconej lub wygranej Więc użyjemy WebSocket jako narzędzia do licytowania i informowania o zmianach w aukcji. Aby rozpocząć aukcję, użytkownik musi wybrać opcję Opcja aukcji w menu Way To Give see Początkowo tylko dwa moduły są załadowane Uświadamiamy sobie, że tylko niewielka liczba użytkowników zdecyduje się wziąć udział w aukcji, która z punktu architektonicznego że kod popierający aukcję powinien być ładowany na żądanie tylko wtedy, gdy użytkownik zdecyduje się na aukcję Dlatego musimy napisać ten kod jako moduł ładowany, a otrzymasz praktyczny przykład tego, jak aplikacja internetowa może być modularyzowane. W tym rozdziale nadal używamy RequireJS zobacz modularizingjavascriptprojects jako ramy dla modularyzacji Używając RequireJS, będziemy leniwie załadować niektóre moduły, jeśli tylko i tylko wtedy, gdy są one wymagane przez użytkownika. Książka ta dotyczy rozwoju użytkownika interfejs i strona klienta aplikacji sieciowych, dlatego nie obejmiemy wszystkich szczegółów związanych z implementacją po stronie serwera, ale umożliwi nam udostępnienie naszego kodu po stronie serwera Utrzymujemy nasz serwer i uruchamiamy go, aby można było przetestować interfejs użytkownika odwiedzając, ale naszym głównym celem w tej sekcji jest pokazanie, w jaki sposób można wymieniać dane z licytacją na serwerze i przetwarzać je po stronie klienta przy użyciu WebSocket. Użyjemy serwera aplikacji Java GlassFish 4, który jest refe rence implementacji specyfikacji Java EE 7. Autorzy tej książki stanowią twórcy języka Java i nagraliśmy screencast pod hasłem WebSocket server API. Jeśli nie jesteś twórcą Javy, możesz się nauczyć samodzielnie, na którym istnieją serwery WebSocket Twój ulubiony język programowania lub platforma. modularizingjavascriptprojects demonstruje jak aplikacja internetowa może być podzielona na kilka modułów przy użyciu frameworku RequireJS Będziemy używać tego projektu jako bazy i stworzyć nową, projektową-16-websocket-auction dodając do niej nowe moduły wspierające moduł aukcyjny WayToGive kod modułu WayToGive. Przykład 6 modułu WayToGive. Po uruchomieniu aplikacji RequireJS załaduje tylko istotne moduły, login i podarunek, jak pokazano na wstępie, tylko dwa moduły są załadowane. W konsoli Narzędzia dla programistów Google Chrome można zobaczyć, że moduły logowania i donacji informują o pomyślnym załadowaniu Dwa moduły są ładowane podczas uruchamiania aplikacji Save the Child potwierdza, że ​​te moduły działają prawidłowo, klikając przycisk Donate Now, który ujawnia ten formularz, a kliknięcie przycisku Login powoduje, że pola ID i hasła są widoczne. 4 Początkowo ładowane są tylko dwa moduły. Rysunek 5 W trakcie uruchamiania programu Save the Child wczytuje się dwa moduły. Kliknij przycisk W ay Aby nadać menu i obserwować konsolę narzędzi dla programistów, zobacz Kontrolery aukcji są ładowane i renderowane Widać moduł modułu WayToGive zgłaszający informacje o jego ładowaniu i renderowaniu. figura 6 Kontrolki aukcji są ładowane i renderowane. Kiedy użytkownik kliknie Way To Podaj, framework RequireJS musi załadować kod modułu aukcyjnego opartego na technologii WebSocket Wczytywanie sposobu podawania modułu przedstawia fragment kodu z pliku JavaScript punkt początkowy naszej aplikacji Zapisz dziecko Jest to, jak ładuje moduł na żądanie zobacz modularizingjavascriptprojects for RequireJS refresher. Example 7 Wczytywanie sposobu podawania modułu. Formowanie komunikatu o prośbie Możesz zapoznać się z formatem wiadomości w artykule Tworzenie protokół aukcji dla aukcji dla dzieci. Sprawdź stan obiektu WebSocket. Jeśli program WebSocket jest otwarty, to readyState 1 aplikacja może wysłać wiadomość Jeśli nie, ten kod po prostu rejestruje mesage offline na konsoli W prawdziwym świecie zawsze powinieneś wyświetlać tę wiadomość na użytkownikach UI Również, jeśli użytkownicy pracują na niestabilnych sieciach, takich jak komórkowe lub 3G, na pewno nie chcesz tracić żadnych danych. Dobrym pomysłem jest użycie lokalnego interfejsu API przechowywania danych, aby zobaczyć dane na bieżąco, by nadal utrzymywać dane lokalnie, aż aplikacja wróci do trybu online i ponownie umieść dane. Użytkownik może wybrać partię aukcji z pola kombi i zobaczyć jej obrazy Konsola loguje wiadomości przychodzące zawierające listę aukcji pokazuje, jakie są wyświetlane na konsoli, podczas gdy liczby i pokazywanie zawartości karty sieciowej dla oba obrazy. Konfigura 7 Konsola loguje wiadomości przychodzące zawierające listę elementów aukcji. Kryształ 8 Korzystając z funkcji sieciowej programu DevTools, możemy monitorować klatki WebSocket. Rysunek 9 Kupujący może wybrać inną pozycję, na którą chcesz licytować. Monitorowanie ruchu w sieci WebSocket przez Korzystanie z narzędzi dla programistów firmy Chrome. Następnie sprawdź praktyczne zastosowanie teorii opisanej w usłudze Handshake w usłudze WebSocket Za pomocą narzędzi dla programistów Chrome można monitorować informacje dotyczące początkowego uzgadniania, jak pokazano w początkowym uścisku uzgadniania WebSocket w Chrome DevTools Monitorowanie ruchu w witrynie WebSocket w Narzędziach dla programistów w Chrome jest w pewien sposób inny niż monitorowanie żądań. Po wybraniu ścieżki punktu końcowego WebSocket w lewym panelu można zobaczyć ruch na karcie Sieć. kliknij przycisk WebSockets w prawym dolnym rogu, aby wyświetlić tylko punkty końcowe serwera WebSocket Kliknij kartę Ramki w prawym panelu, aby wyświetlić rzeczywiste ramki wymieniane między klientem a serwerem, jak pokazano na stronie Monitorowanie klatek sieci WebSocket w Narzędziach dla programistów w przeglądarce Chrome białe wiersze reprezentują przychodzące dane w kolorze zielonym lub szarym na papierze wskazują dane wychodzące. Rysunek 10 Uruchomienie początkowe produktu WebSocket w Chrome DevTools. Figure 11 Monitorowanie ramek WebSocket w narzędziu dla programistów firmy Chrome. Aby uzyskać więcej informacji, możesz nawigować w przeglądarce Google Chrome do tajnych URL-chrome net-internals zawiera wiele użytecznych informacji na ten rysunek i możesz znaleźć dokumentację dotyczącą elementów net-internals w dokumentach z dokumentacją Chromium Design. Figure 1 2 Szczegóły wstępnego uzgadniania w przeglądarkach sieciowych Chrome. Narzędzia dla programistów Google pokazują tylko długość danych. Chromowane siatki pokazują rozmiar ramki WebSocket, a narzędzia programistyczne i net-internals obok siebie porównują widoki net-internals i Developer Tools Jak nauczyłeś się wcześniej w tym rozdziale, całkowity rozmiar ramki jest nieco inny od rozmiaru ładunkowego Jest kilka dodatkowych bajtów nagłówka ramki Ponadto wszystkie wiadomości wychodzące będą maskowane przez przeglądarkę zobacz anatomia ramki WebSocket Ta maska ​​ramki zostanie przekazana do serwera jako część samej ramki, która tworzy dodatkowe 32 bity 4 bajtów napowietrznych. figura 13 Szczegóły połączenia gniazda. Figure 14 Narzędzia dla programistów i net - internals, side by side. Sniffing WebSocket Frames przy użyciu Wireshark. Wireshark jest potężnym i wszechstronnym narzędziem do monitorowania ruchu sieciowego Możesz pobrać go ze strony internetowej Wireshark Aby rozpocząć przechwytywanie WebSocket tr affic na localhost wybierz interfejs sieciowy pętli zwrotnej z lewego panelu i kliknij przycisk Start, aby zobaczyć główny widok aplikacji aplikacji Wireshark. Rysunek 15 Widok główny aplikacji Wireshark. Wireshark przechwytuje całą aktywność w sieci Możesz skonfigurować filtr, aby zobaczyć tylko dane, w których jesteś Zainteresowany Chcę przechwytywać i ruch TCP na porcie 8080, ponieważ nasz serwer WebSocket firmy Oracle GlassFish działa w tym porcie, zobacz Instalacja filtru Wprowadź tekst w polu tekstowym filtru i kliknij przycisk Zastosuj. Zestaw 16 konfiguracji filtra. Następnie Wireshark jest gotowy wyczuć ruch nasza aplikacja Możesz rozpocząć sesję aukcyjną i składać oferty Po wykonaniu aukcji możesz powrócić do okna Wireshark i przeanalizować wyniki Możesz zobaczyć początkowe żądanie GET w żądaniu GET dla aktualizacji protokołu i odpowiedzi na aktualizację w Odpowiedź GET z uaktualnieniem protokołu. Faktura 17 Żądanie GET dla uaktualnienia protokołu. Rejak 18 Odpowiedź GET z uaktualnieniem protokołu. Po pomyślnym uaktualnieniu połączenia, rekina odbiera strumień tak przedstawia raport ruchu WebSocket w porcie 8080 Kliknij prawym przyciskiem myszy ten wiersz i wybierz Follow TCP Stream, jak pokazano w menu Follow the TCP Stream. Graj 19 Menu Follow TCP Stream na następnym ekranie można zobaczyć szczegóły ramki WebSocket Zobacz sekcję WebSocket Zrobiliśmy ten zrzut ekranu zaraz po uruchomieniu aplikacji aukcyjnej Możesz zobaczyć dane z listą dostępnych aukcji Dane wychodzące wyświetlane są na czerwono, a przychodzące dane są wyświetlane na niebiesko. 20 Ramka WebSocket Zrzut ekranu wyświetlany w całej rozmowie aukcyjnej został podjęty po zamknięciu aukcji Możesz zobaczyć wszystkie dane wysłane przez połączenie WebSocket. Grafika 21 Cała rozmowa aukcyjna. Ustanowienie protokołu Zapisywanie aukcji dzieci Ze względu na to, że WebSocket jest właśnie protokołu transportowego, musimy wymyślić protokół poziomu aplikacji, wskazujący, jak powinny być sformatowane wiadomości aukcyjne w interakcji z klientem-serwerem. Tak właśnie postanowiliśmy to zrobić. Klient s co de łączy się z punktem końcowym WebSocket na serwerze. Klient wysyła wiadomość AUCTIONLIST, aby pobrać listę aktualnie prowadzonych aukcji. Po zakończeniu aukcji serwer wysyła wiadomość z końcowymi wynikami aukcji Jeśli użytkownik winien jest online i połączony na serwer aukcyjny, że użytkownik otrzyma wiadomość z gratulacjami Inni uczestnicy otrzymają Sorry, nie wygrałeś powiadomienia. To dość dużo Kwota kodu potrzebnego do wdrożenia strony klienta po stronie aukcji jest minimalna Po połączeniu a aktualizacja jest wykonywana, większość przetwarzania jest wykonywana w obsługi wiadomości dla obiektu WebSocket. Po przeczytaniu tego rozdziału, powinieneś zobaczyć zalety korzystania z protokołu WebSocket w aplikacjach internetowych W wielu przypadkach WebSocket jest ostatecznym narzędziem do poprawienie wydajności aplikacji poprzez zmniejszenie opóźnienia sieci i usunięcie napowietrzania nagłówków Nauczyłeś się integrować funkcjonalność opartą na technologii WebSocket w programie Exis ting Zapisz dziecko Nie ma potrzeby nawiązywania komunikacji z aplikacją internetową za pośrednictwem usługi WebSocket Użyj tego potężnego protokołu, jeśli poprawiasz wydajność i szybkość reakcji aplikacji. Jako korzyść dla strony nauczyłeś się korzystać z funkcji monitorowania sieci Google Narzędzia dla programistów Chrome i Wireshark przez wąskiwanie ruchu w sieci WebSocket Nie można lekceważyć znaczenia narzędzi monitorowania, które są najlepszymi przyjaciółmi twórców stron internetowych. Ta klasa reprezentuje serwer WebSocket Rozszerza EventEmitter. new callback. host Nazwa hosta, na której można powiązać server. port Port, w którym ma się powiązać serwer. backlog Maksymalna długość kolejki oczekujących na połączenia. server Serwer. verifyClient utworzony wcześniej Funkcja, która może być użyta do sprawdzania poprawności połączeń przychodzących Patrz opis poniżej. handleProtocols Funkcja, która może być używany do obsługi subprotologów WebSocket Zobacz opis poniżej. path Przyjmij tylko połączenia pasujące do tej ścieżki. noServer Enable no se rver mode. clientTracking Określa, czy śledzić clients. perMessageDeflate Enable disable permessage-deflate. maxPayload Maksymalna dopuszczalna wielkość wiadomości w bajtach. Utwórz nową instancję serwera Należy podać jeden serwer portowy lub noServer lub wyrzucić błąd. Jeśli zweryfikujesz klienta nie jest ustawiona, wtedy uzgadnianie jest automatycznie akceptowane Jeśli jest dostarczony z pojedynczym argumentem, to jest to. origin Wartość w nagłówku Origin wskazana przez client. req Żądanie klienta GET. true jeśli lub jest ustawiona. Wartość zwracana Boolean funkcji określa, czy akceptować handshake. if verifyClient jest dostarczany z dwoma argumentami, a następnie tymi are. info Tak samo jak powyżej. cb Odwołanie zwrotne, które musi być wywołane przez użytkownika po sprawdzeniu pól info Argumenty w tym callbacku są. result Czy przyjmowanie kodu handshake. code Gdy wynik jest fałszywy, to pole określa kod statusu błędu, który ma zostać przesłany do klienta. name Gdy wynik jest false, to pole określa przyczynę ph rase. If handleProtocols nie jest ustawiony, wtedy uzgadnianie jest automatycznie akceptowane, w przeciwnym wypadku funkcja przyjmuje pojedynczy argument. protocols Lista podprotokołów WebSocket wskazanych przez klienta w nagłówku protokołu Sec-WebSocket. Jeśli wartość zwrócona jest false, to uzgadnianie jest odrzucony kodem stanu 401, w przeciwnym razie wartość zwrócona ustawia wartość nagłówka protokołu Sec-WebSocket w odpowiedzi na 101. zdarzenieTerapDeflate może być użyte do kontrolowania zachowania rozszerzenia depesji-wysuniętej Rozszerzenie jest wyłączone, jeśli false Domyślne wartości to true If obiekt jest pod warunkiem, że jest to parametry rozszerzenia. serverNoContextTakeover Czy użyj kontekstu przejmij lub nie. clientNoContextTakeover Wartość wymagana klientom, czy ma zostać przejęty kontekst, czy nie. serverMaxWindowBits Wartość windowBits. clientMaxWindowBits Wartość maks. windowBits do do request. memLevel Wartość memLevel. threshold Ładunki mniejsze od tego nie będą kompresowane Domyślnie s do 1024 bajtów. Jeśli dana własność jest pusta, wówczas użyta jest oferowana konfiguracja lub domyślna wartość W przypadku wysyłania fragmentowanej wiadomości długość pierwszego fragmentu jest porównywana z wartością progową To określa, czy kompresja jest używana dla całej wiadomości. callback być dodawany jako słuchacz zdarzenia odsłuchiwania, gdy serwer jest tworzony wewnętrznie i to jest, gdy opcja portu jest dostarczona. Podłączone, gdy uzgadnianie jest kompletne gniazdo jest wystąpieniem WebSocket. Połączenie jest zamknięte. Nowy adres sieci Web, protokoły, opcje Adres URL, do którego mają się łączyć. protocols Lista podprotokołów. protocol Wartość nagłówka protokołu Sec-WebSocket header. perMessageDeflate Enable disable permessage-deflate. localAddress Lokalny interfejs do powiązania połączeń sieciowych. protocolVersion Wartość Sec-WebSocket - Nagłówek wersji Obiekt z niestandardowymi nagłówkami do wysłania wraz z żądaniem. origin Wartość nagłówka Origin lub Sec-WebSocket-Origin w zależności od protokołuVersio n. agent Użyj określonej wartości agenta. host Wartość rodziny adresów IP header. family hosta do używania podczas wyszukiwania nazw hostów 4 lub 6.checkServerIdentity Funkcja sprawdzania poprawności nazwy hosta serwera. rejectUnazweryfikowana Zweryfikuj certyfikat serwera. passphrase Pseudonim klucz prywatny lub pfx. ciphers Szyfry do używania lub wykluczania. cert Klawisze certyfikatów. key Prywatny klucz. pfx Prywatne klucze, certyfikaty i certyfikaty CA. Certyfikowane certyfikaty. perMessageDeflate są identyczne z serwerem, jedyną różnicą jest kierunek żądań, np. serverNoContextTakeover to wartość, którą należy żądać na serwerze. Utwórz nową instancję WebSocket. UNIX Sockets Sockets. ws obsługuje żądania gniazd UNIX w domenie Aby utworzyć jedną z nich, użyj następującego schematu adresu URL. Należy zauważyć, że jest to separator pomiędzy ścieżką adresową a ścieżką adresu URL Jeśli ścieżka adresu URL jest pomijana. Zajawione, gdy połączenie jest zamknięte kod to wartość liczbowa wskazująca kod stanu wyjaśniający, dlaczego połączenie było bliskie d jest łańcuchem czytelnym dla człowieka, wyjaśniającym, dlaczego połączenie zostało zamknięte. Zostało pomyślane, gdy wystąpi błąd Błędy z podstawy są przekazywane tutaj. Zajawione, gdy wiadomość jest otrzymywana z serwera. Zajawione, gdy otrzymano pong z serwera. Zazwolone gdy odpowiedź serwera nie jest oczekiwana, na przykład odpowiedź 401 To zdarzenie umożliwia odczytanie odpowiedzi w celu wyodrębnienia użytecznych informacji Jeśli serwer wysyła nieprawidłową odpowiedź i nie jest on nasłuchujący tego zdarzenia, zostanie wysłany błąd. type A string representing the event type to listen for. listener The listener to add. Register an event listener emulating the EventTarget interface. A string indicating the type of binary data being transmitted by the connection This should be one of nodebuffer , arraybuffer or fragments Defaults to nodebuffer Type fragments will emit the array of fragments as received from the sender, without copyfull concatenation, which is useful for the performance of binary p rotocols transfering large messages with multiple fragments. The number of bytes of data that have been queued using calls to send but not yet transmitted to the network. Received bytes count. code A numeric value indicating the status code explaining why the connection is being closed. reason A human-readable string explaining why the connection is closing. Initiate a closing handshake. An object containing the negotiated extensions. An event listener to be called when connection is closed The listener receives a CloseEvent named close. An event listener to be called when an error occurs The listener receives an Error instance. An event listener to be called when a message is received from the server The listener receives a MessageEvent named message. An event listener to be called when the connection is established The listener receives an OpenEvent named open. Pause the socket. mask , failSilently. data The data to send in the ping frame. mask Specifies whether data should be masked or not Defaults to true when websocket is not a server client. failSilently Specifies whether or not to throw an error if the connection is not open. mask , failSilently. data The data to send in the ping frame. mask Specifies whether data should be masked or not Defaults to true when websocket is not a server client. failSilently Specifies whether or not to throw an error if the connection is not open. The subprotocol selected by the server. The WebSocket protocol version used for this connection, 8 or 13.The current state of the connection This is one of the ready state constants. type A string representing the event type to remove. listener The listener to remove. Removes an event listener emulating the EventTarget interface. Resume the socket. options , callback. data The data to sendpress Specifies whether data should be compressed or not Defaults to true when permessage-deflate is enabled. binary Specifies whether data should be sent as a binary or not Default is autodetected. mask Specifies whether data should be masked or not Defaults to true when websocket is not a server client. fin Specifies whether data is the last fragment of a message or not Defaults to true. callback An optional callback which is invoked when data is written out. Send data through the connection. Forcibly close the connection. The GET request sent by the client Useful for parsing authority headers, cookie headers, and other information This is only available for server clients. The URL of the WebSocket server Server clients don t have this attribute. What s different in the new WebSocket protocol. Developer Advocate in Tokyo. The WebSocket protocol specification has recently been updated to solve previous security concerns and is largely stable Below is a sum mary of the changes involved, along with some notes on current implementations. What has been changed since WebSocket HyBi 00.The protocol frame format has been changed HyBi 00 used to use 0x00 for head and 0xff for tail for each frame HyBi 10 now uses new format like following. Security issues have been addressed. Sec-WebSocket-Key and Sec-WebSocket-Accept are added in place of HyBi 00 s three keys The browser gives randomly generated number to Sec-WebSocket-Key Then, the server uses it with WebSocket protocol s specific GUID 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 and SHA1 BASE64, etc to return Sec-WebSocket-Accept so that browser can confirm that it understands WebSocket This prevents a cross-protocol attack. On each frame, frame masking is now required This prevents cache poisoning on proxy Sec-WebSocket-Origin is added to prevent access from scripts that the service provider isn t aware of. Sec-WebSocket-Origin is added in place of HyBi 00 s Origin key to prevent access from scripts that the service provider doesn t aware of Note that this will be just Origin on HyBi 11.JS API changes. subprotocol can now be array, allowing a method signature of new WebSocket String url, Array subprotocol. attribute String. attribute Blob ArrayBuffer. Status code and reason why the connection is closed have been added to CloseEvent The close function has also been changed to accept these two arguments accordingly. Sec-WebSocket-Extensions is added Proposed extensions are. deflate-frame makes frames compressed at source and extracted at destination. x-google-mux to support multiplexing but is in early stage. Is there compatibility between HyBi 00 and HyBi 10 on both server and browser implementation. Server implementations can support both HyBi 00 and HyBi 10 by looking at the handshake header However, it is not recommended to support HyBi 00 since it s known to be vulnerable. The WebSocket JavaScript API is largely similar between old and new versions But as noted above, we don t recommend supporting HyBi 00 since it s known to be vulnerable. Which browser support HyBi 10.Chrome 14 supports HyBi 10 protocol although the WebSocket JavaScript API changes mentioned above are still on the way Firefox 7 is also planne d to support HyBi 10.Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 3 0 License and code samples are licensed under the Apache 2 0 License For details, see our Site Policies Java is a registered trademark of Oracle and or its affiliates. 28, 2017.The latest news on the Chromium blog. Fork our API code samples and other open-source projects. Connect with ChromiumDev on Twitter. Check out the Web Developer Relations team s videos. Attend a developer event and get hacking. Contribute to WebFundamentals. High Performance Browser Networking by Ilya Grigorik. Chapter 17 WebSocket. WebSocket enables bidirectional, message-oriented streaming of text and binary data between client and server It is the closest API to a raw network socket in the browser Except a WebSocket connection is also much more than a network socket, as the browser abstracts all the complexity behind a simple API and provides a number of additional services. Connection negotiation and same-origin policy enforcement. Interoperability with existing infrastructure. Message-oriented communication and efficient message framing. Subprotocol negotiation and extensibility. WebSocket is one of the most versatile and flexible transports available in the browser The simple and min imal API enables us to layer and deliver arbitrary application protocols between client and server anything from simple JSON payloads to custom binary message formats in a streaming fashion, where either side can send data at any time. However, the trade-off with custom protocols is that they are, well, custom The application must account for missing state management, compression, caching, and other services otherwise provided by the browser There are always design constraints and performance trade-offs, and leveraging WebSocket is no exception In short, WebSocket is not a replacement for XHR, or SSE, and for best performance it is critical that we leverage the strengths of each transport. WebSocket is a set of multiple standards the WebSocket API is defined by the W3C, and the WebSocket protocol RFC 6455 and its extensions are defined by the HyBi Working Group IETF. WebSocket API. The WebSocket API provided by the browser is remarkably small and simple Once again, all the low-level detail s of connection management and message processing are taken care of by the browser To initiate a new connection, we need the URL of a WebSocket resource and a few application callbacks. Open a new secure WebSocket connection wss. Optional callback, invoked if a connection error has occurred. Optional callback, invoked when the connection is terminated. Optional callback, invoked when a WebSocket connection is established. Client-initiated message to the server. A callback function invoked for each new message from the server. Invoke binary or text processing logic for the received message. The API speaks for itself In fact, it should look very similar to the EventSource API we saw in the preceding chapter This is intentional, as WebSocket offers similar and extended functionality Having said that, there are a number of important differences as well Let s take a look at them one by one. WebSocket protocol has undergone a number of revisions, implementation rollbacks, and security investigations However, the good news is that the latest version v13 defined by RFC6455 is now supported by all modern browsers The only notable omission is the Android browser For the latest status, see. Similar to the SSE polyfill strategy Emulating EventSource with Custom JavaScript , the WebSocket browser API can be emulated via an optional JavaScript library However, the hard part with emulating WebSockets is not the API, but the transport As a result, the choice of the polyfill library and its fallback transport XHR polling, EventSource, iframe polling, etc will have significant impact on the performance of an emulated WebSocket session. To simplify cross-browser deployment, popular libraries such as SockJS provide an implementation of WebSocket-like object in the browser but also go one step further by providing a custom server that implements support for WebSocket and a variety of alternative transports The combination of a custom server and client is what enables seamless fallback the performa nce suffers, but the application API remains the same. Other libraries, such as go even further by implementing additional features, such as heartbeats, timeouts, support for automatic reconnects, and more, in addition to a multitransport fallback functionality. When considering a polyfill library or a real-time framework, such as pay close attention to the underlying implementation and configuration of the client and server always leverage the native WebSocket interface for best performance, and ensure that fallback transports meet your performance goals. WS and WSS URL Schemes. The WebSocket resource URL uses its own custom scheme ws for plain-text communication e g , and wss when an encrypted channel TCP TLS is required Why the custom scheme, instead of the familiar. The primary use case for the WebSocket protocol is to provide an optimized, bi-directional communication channel between applications running in the browser and the server However, the WebSocket wire protocol can be used out side the browser and could be negotiated via a exchange As a result, the HyBi Working Group chose to adopt a custom URL scheme. Despite the negotiation option enabled by the custom scheme, in practice there are no existing standards for alternative handshake mechanisms for establishing a WebSocket session. Receiving Text and Binary Data. WebSocket communication consists of messages and application code and does not need to worry about buffering, parsing, and reconstructing received data For example, if the server sends a 1 MB payload, the application s onmessage callback will be called only when the entire message is available on the client. Further, the WebSocket protocol makes no assumptions and places no constraints on the application payload both text and binary data are fair game Internally, the protocol tracks only two pieces of information about the message the length of payload as a variable-length field and the type of payload to distinguish UTF-8 from binary transfers. When a new message is received by the browser, it is automatically converted to a DOMString object for text-based data, or a Blob object for binary data, and then passed directly to the application The only other option, which acts as performance hint and optimization for the client, is to tell the browser to convert the received binary data to an ArrayBuffer instead of Blob. Force an ArrayBuffer conversion when a binary message is received. User agents can use this as a hint for how to handle incoming binary data if the attribute is set to blob , it is safe to spool it to disk, and if it is set to arraybuffer , it is likely more efficient to keep the data in memory Naturally, user agents are encouraged to use more subtle heuristics to decide whether to keep incoming data in memory or not. The WebSocket API W3C Candidate Recommendation. A Blob object represents a file-like object of immutable, raw data If you do not need to modify the data and do not need to slice it into smaller chunks, then it is the optimal format e g you can pass the entire Blob object to an image tag see the example in Downloading Data with XHR On the other hand, if you need to perform additional processing on the binary data, then ArrayBuffer is likely the better fit. Decoding Binary Data with JavaScript. An ArrayBuffer is a generic, fixed-length binary data buffer However, an ArrayBuffer can be used to create one or more ArrayBufferView objects, each of which can present the contents of the buffer in a specific format For example, let s assume we have the following C-like binary data structure. Given an ArrayBuffer object of this type, we can create multiple views into the same buffer, each with its own offset and data type. Each view takes the parent buffer, starting byte offset, and number of element s to process the offset is calculated based on the size of the preceding fields As a result, ArrayBuffer and WebSocket give our applications all the necessary tools to stream and process binary data within the browser. Sending Text and Binary Data. Once a WebSocket connection is established, the client can send and receive UTF-8 and binary messages at will WebSocket offers a bidirectional communication channel, which allows message delivery in both directions over the same TCP connection. Send a UTF-8 encoded text message. Send a UTF-8 encoded JSON payload. Send the ArrayBuffer contents as binary payload. Send the ArrayBufferView contents as binary payload. Send the Blob contents as binary payload. The WebSocket API accepts a DOMString object, which is encoded as UTF-8 on the wire, or one of ArrayBuffer, ArrayBufferView, or Blob objects for binary transfers However, note that the latter binary options are simply an API convenience on the wire, a WebSocket frame is either marked as binary or te xt via a single bit Hence, if the application, or the server, need other content-type information about the payload, then they must use an additional mechanism to communicate this data. The send method is asynchronous the provided data is queued by the client, and the function returns immediately As a result, especially when transferring large payloads, do not mistake the fast return for a signal that the data has been sent To monitor the amount of data queued by the browser, the application can query the bufferedAmount attribute on the socket. Subscribe to application updates e g game state changes. Check the amount of buffered data on the client. Send the next update if the buffer is empty. The preceding example attempts to send application updates to the server, but only if the previous messages have been drained from the client s buffer Why bother with such checks All WebSocket messages are delivered in the exact order in which they are queued by the client As a result, a large backlog of queued messages, or even a single large message, will delay delivery of messages queued behind it head-of-line blocking. To work around this problem, the application can split large messages into smaller chunks, monitor the bufferedAmount value carefully to avoid head-of-line blocking, and even implement its own priority queue for pending messages instead of blindly queuing them all on the socket. Many applications generate multiple classes of messages high-priority updates, such as control traffic, and low-priority updates, such as background transfers To optimize delivery, the application should pay close attention to how and when each type of message is queued on the socket. Subprotocol Negotiation. WebSocket protocol makes no assumptions about the format of each message a single bit tracks whether the message contains text or binary data, such that it can be efficiently decoded by the client and server, but otherwise the message contents are opaque. Further, unlike or XHR requests, w hich communicate additional metadata via headers of each request and response, there is no such equivalent mechanism for a WebSocket message As a result, if additional metadata about the message is required, then the client and server must agree to implement their own subprotocol to communicate this data. The client and server can agree on a fixed message format upfront e g all communication will be done via JSON-encoded messages or a custom binary format, and necessary message metadata will be part of the encoded structure. If the client and server need to transfer different data types, then they can agree on a consistent message header, which can be used to communicate the instructions to decode the remainder of the payload. A mix of text and binary messages can be used to communicate the payload and metadata information e g a text message can communicate an equivalent of headers, followed by a binary message with the application payload. This list is just a small sample of possible stra tegies The flexibility and low overhead of a WebSocket message come at the cost of extra application logic However, message serialization and management of metadata are only part of the problem Once we determine the serialization format for our messages, how do we ensure that both client and server understand each other, and how do we keep them in sync. Thankfully, WebSocket provides a simple and convenient subprotocol negotiation API to address the second problem The client can advertise which protocols it supports to the server as part of its initial connection handshake. Array of subprotocols to advertise during WebSocket handshake. Check the subprotocol chosen by the server. As the preceding example illustrates, the WebSocket constructor accepts an optional array of subprotocol names, which allows the client to advertise the list of protocols it understands or is willing to use for this connection The specified list is sent to the server, and the server is allowed to pick one of the pr otocols advertised by the client. If the subprotocol negotiation is successful, then the onopen callback is fired on the client, and the application can query the protocol attribute on the WebSocket object to determine the chosen protocol On the other hand, if the server does not support any of the client protocols advertised by the client, then the WebSocket handshake is incomplete the onerror callback is invoked, and the connection is terminated. The subprotocol names are defined by the application and are sent as specified to the server during the initial handshake Other then that, the specified subprotocol has no effect on the core WebSocket API. WebSocket Protocol. The WebSocket wire protocol RFC 6455 developed by the HyBi Working Group consists of two high-level components the opening handshake used to negotiate the parameters of the connection and a binary message framing mechanism to allow for low overhead, message-based delivery of both text and binary data. The WebSocket Protocol attempts to address the goals of existing bidirectional technologies in the context of the existing infrastructure as such, it is designed to work over ports 80 and 443 However, the design does not limit WebSocket to and future implementations could use a simpler handshake over a dedicated port without reinventing the entire protocol. WebSocket Protocol RFC 6455.WebSocket protocol is a fully functional, standalone protocol that can be used outside the browser Having said that, its primary application is as a bidirectional transport for browser-based applications. Binary Framing Layer. Client and server WebSocket applications communicate via a message-oriented API the sender provides an arbitrary UTF-8 or binary payload, and the receiver is notified of its delivery when the entire message is available To enable this, WebSocket uses a custom binary framing format Figure 17-1 , which splits each application message into one or more frames transports them to the destination, reassembles them, and finally notifies the receiver once the entire message has been received. Figure 17-1 WebSocket frame 2 14 bytes payload. Frame The smallest unit of communication, each containing a variable-length frame header and a payload that may carry all or part of the application message Message A complete sequence of frames that map to a log ical application message. The decision to fragment an application message into multiple frames is made by the underlying implementation of the client and server framing code Hence, the applications remain blissfully unaware of the individual WebSocket frames or how the framing is performed Having said that, it is still useful to understand the highlights of how each WebSocket frame is represented on the wire. The first bit of each frame FIN indicates whether the frame is a final fragment of a message A message may consist of just a single frame. The opcode 4 bits indicates type of transferred frame text 1 or binary 2 for transferring application data or a control frame such as connection close 8 , ping 9 , and pong 10 for connection liveness checks. The mask bit indicates whether the payload is masked for messages sent from the client to the server only. Payload length is represented as a variable-length field. If 0 125, then that is the payload length. If 126, then the following 2 bytes repr esent a 16-bit unsigned integer indicating the frame length. If 127, then the following 8 bytes represent a 64-bit unsigned integer indicating the frame length. Masking key contains a 32-bit value used to mask the payload. Payload contains the application data and custom extension data if the client and server negotiated an extension when the connection was established. The payload of all client-initiated frames is masked using the value specified in the frame header this prevents malicious scripts executing on the client from performing a cache poisoning attack against intermediaries that may not understand the WebSocket protocol For full details of this attack, refer to Talking to Yourself for Fun and Prot presented at W2SP 2011.As a result, each server-sent WebSocket frame incurs 2 10 bytes of framing overhead The client must also send a masking key, which adds an extra 4 bytes to the header, resulting in 6 14 bytes over overhead No other metadata, such as header fields or other informa tion about the payload, is available all WebSocket communication is performed by exchanging frames that treat the payload as an opaque blob of application data. WebSocket Multiplexing and Head-of-Line Blocking. WebSocket is susceptible to head-of-line blocking messages can be split into one or more frames, but frames from different messages can t be interleaved, as there is no equivalent to a stream ID found in the 2 0 framing mechanism see Streams, Messages, and Frames. As a result, a large message, even when split into multiple WebSocket frames, will block the delivery of frames associated with other messages If your application is delivering latency-sensitive data, be careful about the payload size of each message and consider splitting large messages into multiple application messages. The lack of multiplexing in core WebSocket specification also means that each WebSocket connection requires a dedicated TCP connection, which may become a potential problem for 1 x deployments due to a r estricted number of connections per origin maintained by the browser see Exhausting Client and Server Resources. On the bright side, the new Multiplexing Extension for WebSockets developed by the HyBi Working Group addresses the latter limitation. With this extension, one TCP connection can provide multiple virtual WebSocket connections by encapsulating frames tagged with a channel ID The multiplexing extension maintains separate logical channels, each of which provides fully the logical equivalent of an independent WebSocket connection, including separate handshake headers. WebSocket Multiplexing Draft 10.With this extension in place, multiple WebSocket connections channels can be multiplexed over the same TCP connection However, each individual channel is still susceptible to head-of-line blocking Hence, one potential workaround is to use different channels, or dedicated TCP connections, to multiplex multiple messages in parallel. Finally, note that the preceding extension is necessary only for 1 x connections While no official specification is yet available for transporting WebSocket frames with 2 0, doing so would be much easier 2 0 has built-in stream multiplexing, and multiple WebSocket connections could be transported within a single session by encapsulating WebSocket frames within the 2 0 framing mechanism. Protocol Extensions. WebSocket specification allows for protocol extensions the wire format and the semantics of the WebSocket protocol can be extended with new opcodes and data fields While somewhat unusual, this is a very powerful feature, as it allows the client and server to implement additional functionality on top of the base WebSocket framing layer without requiring any intervention or cooperation from the application code. What are some examples of WebSocket protocol extensions The HyBi Working Group, which is responsible for the development of the WebSocket specification, lists two official extensions in development. A Multiplexing Extension for WebSockets This extension provides a way for separate logical WebSocket connections to share an underlying transport connection Compression Extensions for WebSocket A framework for creating WebSocket extensions that add compression functionality to the WebSocket Protocol. As we noted earlier, each WebSocket connection requires a dedicated TCP connection, which is inefficient Multiplexing extension addresses this problem by extending each WebSocket frame with an additional channel ID to allow multiple virtual WebSocket channels to share a single TCP connection. Similarly, the base WebSocket specification provides no mechanism or provisions for compression of transferred data each frame carries payload data as provided by the application As a result, while this may not be a problem for optimized binary data structures, this can result in high byte transfer overhead unless the application implements its own data compression and decompression logic In effect, com pression extension enables an equivalent of transfer-encoding negotiation provided by. To enable one or more extensions, the client must advertise them in the initial Upgrade handshake, and the server must select and acknowledge the extensions that will be used for the lifetime of the negotiated connection For a hands-on example, let s now take a closer look at the Upgrade sequence. WebSocket Multiplexing and Compression in the Wild. As of mid-2017, WebSocket multiplexing is not yet supported by any popular browser Similarly, there is limited support for compression Google Chrome and the latest WebKit browsers may advertise an x-webkit-deflate-frame extension to the server However, deflate-frame is based on an outdated revision of the standard and will be deprecated in the future. As the name implies, per-frame compresses the payload contents on a frame-by-frame basis, which is suboptimal for large messages that may be split between multiple frames As a result, latest revisions of the comp ression extension have switched to per-message compression that s the good news The bad news is per-message compression is still experimental and is not yet available in any popular browser. As a result, the application should pay close attention to the content-type of transferred data and apply its own compression where applicable That is, at least until native WebSocket compression support is available widely across all the popular browsers This is especially important for mobile applications, where each unnecessary byte carries high costs to the user. Upgrade Negotiation. The WebSocket protocol delivers a lot of powerful features message-oriented communication, its own binary framing layer, subprotocol negotiation, optional protocol extensions, and more As a result, before any messages can be exchanged, the client and server must negotiate the appropriate parameters to establish the connection. Leveraging to perform the handshake offers several advantages First, it makes WebSockets compatible with existing infrastructure WebSocket servers can run on port 80 and 443, which are frequently the only open ports for the client Second, it allows us to reuse and extend the Upgrade flow with custom WebSocket headers to perform the negotiation. Sec-WebSocket-Version Sent by the client to indicate version 13 for RFC6455 of the WebSocket protocol it wants to use If the server does not support the client version, then it must reply with a list of supported versions Sec-WebSocket-Key An auto-generated key sent by the client, which acts as a challeng e to the server to prove that the server supports the requested version of the protocol Sec-WebSocket-Accept Server response that contains signed value of Sec-WebSocket-Key, proving that it understands the requested protocol version Sec-WebSocket-Protocol Used to negotiate the application subprotocol client advertises the list of supported protocols server must reply with a single protocol name Sec-WebSocket-Extensions Used to negotiate WebSocket extensions to be used for this connection client advertises supported extensions, and the server confirms one or more extensions by returning the same header. With that, we now have all the necessary pieces to perform an Upgrade and negotiate a new WebSocket connection between the client and server. Request to perform an upgrade to the WebSocket protocol. WebSocket protocol version used by the client. Auto-generated key to verify server protocol support. Optional list of subprotocols specified by the application. Optional list of protocol extensions supported by the client. Just like any other client-initiated connection in the browser, WebSocket requests are subject to the same-origin policy the browser automatically appends the Origin header to the upgrade handshake, and the remote server can use CORS to accept or deny the cross origin request see Cross-Origin Resource Sharing CORS To complete the handshake, the server must return a successful Switching Protocols response and confirm the selected options advertised by the client.101 response code confirming WebSocket upgrade. CORS header indicating opt-in for cross-origin connection. Signed Key value proving protocol support. Application subprotocol selected by the server. List of WebSocket extensions selected by the server. All RFC6455-compatible WebSocket servers use the same algorithm to compute the answer to the client challenge the contents of the Sec-WebSocket-Key are concatenated with a unique GUID string defined in the standard, a SHA1 hash is computed, and the resulting stri ng is base-64 encoded and sent back to the client. At a minimum, a successful WebSocket handshake must contain the protocol version and an auto-generated challenge value sent by the client, followed by a 101 response code Switching Protocols from the server with a hashed challenge-response to confirm the selected protocol version. Client must send Sec-WebSocket-Version and Sec-WebSocket-Key. Server must confirm the protocol by returning Sec-WebSocket-Accept. Client may send a list of application subprotocols via Sec-WebSocket-Protocol. Server must select one of the advertised subprotocols and return it via Sec-WebSocket-Protocol If the server does not support any, then the connection is aborted. Client may send a list of protocol extensions in Sec-WebSocket-Extensions. Server may confirm one or more selected extensions via Sec-WebSocket-Extensions If no extensions are provided, then the connection proceeds without them. Finally, once the preceding handshake is complete, and if the handshake is successful, the connection can now be used as a two-way communication channel for exchanging WebSocket messages From here on, there is no other explicit communication between the client and server, and the WebSocket protocol takes over. Proxies, Intermediaries, and WebSockets. In practice, for security and policy reasons, many users have a restricted set of open ports specifically port 80 and port 443 As a result, WebSocket negotiation is performed via the Upgrade flow to ensure the best compatibility with existing network policies and infrastructure. However, as we noted earlier in Proxies, Intermediaries, TLS, and New Protocols on the Web many existing intermediaries may not understand the new WebSocket protocol, which can lead to a variety of failure cases blind connection upgrades, unintended buffering of WebSocket frames, content modification without understanding of the protocol, misclassification of WebSocket traffic as compromised connections, and so on. The WebSocket Key and Acce pt handshake addresses some of these problems it is a security policy against servers and intermediaries that may blindly upgrade the connection without actually understanding the WebSocket protocol However, while this precaution addresses some deployment issues with explicit proxies, it is nonetheless insufficient for transparent proxies, which may analyze and modify the data on the wire without notice. The workaround Establish a secure end-to-end tunnel i e use WSS By negotiating a TLS session prior to performing the Upgrade handshake, the client and server establish an encrypted tunnel, which resolves all of the previously listed concerns This is especially true for mobile clients, whose traffic often passes through a variety of proxy services that may not play well with WebSocket. WebSocket Use Cases and Performance. WebSocket API provides a simple interface for bidirectional, message-oriented streaming of text and binary data between client and server pass in a WebSocket URL to the c onstructor, set up a few JavaScript callback functions, and we are up and running the rest is handled by the browser Add to that the WebSocket protocol, which offers binary framing, extensibility, and subprotocol negotiation, and WebSocket becomes a perfect fit for delivering custom application protocols in the browser. However, just as with any discussion on performance, while the implementation complexity of the WebSocket protocol is hidden from the application, it nonetheless has important performance implications for how and when WebSocket should be used WebSocket is not a replacement for XHR or SSE, and for best performance it is critical that we leverage the strengths of each transport. Refer to XHR Use Cases and Performance and SSE Use Cases and Performance for a review of the performance characteristics of each transport. Request and Response Streaming. WebSocket is the only transport that allows bidirectional communication over the same TCP connection Figure 17-2 the client and se rver can exchange messages at will As a result, WebSocket provides low latency delivery of text and binary application data in both directions. Figure 17-2 Communication flow of XHR, SSE, and WebSocket. XHR is optimized for transactional request-response communication the client sends the full, well-formed request to the server, and the server responds with a full response There is no support for request streaming, and until the Streams API is available, no reliable cross-browser response streaming API. SSE enables efficient, low-latency server-to-client streaming of text-based data the client initiates the SSE connection, and the server uses the event source protocol to stream updates to the client The client can t send any data to the server after the initial handshake. Propagation and Queuing Latency. Switching transports from XHR to SSE or WebSocket does not decrease the roundtrip between client and server Regardless of the transport, the propagation latency of the data packets is the s ame However, aside from propagation latency, there is also the queuing latency the time the message has to wait on the client or server before it can be routed to the other party. In the case of XHR polling, the queuing latency is a function of the client polling interval the message may be available on the server, but it cannot be sent until the next client XHR request see Modeling Performance of XHR Polling By contrast, both SSE and WebSocket use a persistent connection, which allows the server to dispatch the message and client, in the case of WebSocket , the moment it becomes available. As a result, low-latency delivery for SSE and WebSocket is specifically referring to the elimination of message queuing latency We have not yet figured out how to make WebSocket data packets travel faster than the speed of light. Message Overhead. Once a WebSocket connection is established, the client and server exchange data via the WebSocket protocol application messages are split into one or more fra mes, each of which adds from 2 to 14 bytes of overhead Further, because the framing is done via a custom binary format, both UTF-8 and binary application data can be efficiently encoded via the same mechanism How does that compare with XHR and SSE. SSE adds as little as 5 bytes per message but is restricted to UTF-8 content only see Event Stream Protocol. 1 x requests XHR or otherwise will carry an additional 500 800 bytes of metadata, plus cookies see Measuring and Controlling Protocol Overhead. 2 0 compresses the metadata, which significantly reduces the overhead see Header Compression In fact, if the headers do not change between requests, the overhead can be as low as 8 bytes. Keep in mind that these overhead numbers do not include the overhead of IP, TCP, and TLS framing, which add 60 100 bytes of combined overhead per message, regardless of the application protocol see TLS Record Size. Data Efficiency and Compression. Every XHR request can negotiate the optimal transfer encoding format e g gzip for text-based data , via regular negotiation Similarly, because SSE is restricted to UTF-8 only transfers, the event stream data can be efficiently compressed by applying gzip across the entire session. With WebSocket, the situation is more complex WebSocket can transfer both text and binary data, and as a result it doesn t make sense to compress the entire session The binary payloads may be compressed already As a result, WebSocket must implement its own compression mechanism and sel ectively apply it to each message. The good news is the HyBi working group is developing the per-message compression extension for the WebSocket protocol However, it is not yet available in any of the browsers As a result, unless the application implements its own compression logic by carefully optimizing its binary payloads see Decoding Binary Data with JavaScript and implementing its own compression logic for text-based messages, it may incur high byte overhead on the transferred data. Chrome and some WebKit-based browsers support an older revision per-frame compression of the compression extension to the WebSocket protocol see WebSocket Multiplexing and Compression in the Wild. Custom Application Protocols. The browser is optimized for data transfers it understands the protocol, and it provides a wide array of services, such as authentication, caching, compression, and much more As a result, XHR requests inherit all of this functionality for free. By contrast, streaming allows us to deli ver custom protocols between client and server, but at the cost of bypassing many of the services provided by the browser the initial handshake may be able to perform some negotiation of the parameters of the connection, but once the session is established, all further data streamed between the client and server is opaque to the browser As a result, the flexibility of delivering a custom protocol also has its downsides, and the application may have to implement its own logic to fill in the missing gaps caching, state management, delivery of message metadata, and so on. The initial Upgrade handshake does allow the server to leverage the existing cookie mechanism to validate the user If the validation fails, the server can decline the WebSocket upgrade. Leveraging Browser and Intermediary Caches. Using regular has significant advantages Ask yourself a simple question would the client benefit from caching the received data Or could an intermediary optimize the delivery of the asset if it cou ld cache it. For example, WebSocket supports binary transfers, which allows the application to stream arbitrary image formats with no overhead nice win However, the fact that the image is delivered within a custom protocol means that it won t be cached by the browser cache, or any intermediary e g a CDN As a result, you may incur unnecessary transfers to the client and much higher traffic to the origin servers The same logic applies to all other data formats video, text, and so on. As a result, make sure you choose the right transport for the job A simple but effective strategy to address these concerns could be to use the WebSocket session to deliver non-cacheable data, such as real-time updates and application control messages, which can trigger XHR requests to fetch other assets via the protocol. Deploying WebSocket Infrastructure. is optimized for short and bursty transfers As a result, many of the servers, proxies, and other intermediaries are often configured to aggressively timeout idle connections, which, of course, is exactly what we don t want to see for long-lived WebSocket sessions To address this, there are three pieces to consider. Routers, load-balancers, and proxies within own network. Transparent and explicit proxies in external network e g ISP and carrier proxies. Routers, firewalls, and proxies within the client s network. We have no control over the policy of the client s network In fact, some networks may block WebSocket traffic entirely, which is why you may need a fallback strategy Similarly, we don t have control over the proxies on the external network However, this is where TLS may help By tunneling over a secure end-to-end connection, WebSocket traffic can bypass all the intermediate proxies. Using TLS does not prevent the intermediary from timing out an idle TCP connection However, in practice , it significantly increases the success rate of negotiating the WebSocket session and often also helps to extend the connection timeout intervals. Finally, there is the infrastructure that we deploy and manage ourselves, which also often requires attention and tuning As easy as it is to blame the client or external networks, all too often the problem is close to home Each load-balancer, router, proxy, and web server in the serving path must be tuned to allow long-lived connections. For example, Nginx 1 3 13 can proxy WebSocket traffic, but defaults to aggressive 60-second timeouts To increase the limit, we must explicitly define the longer timeouts. Set 60-minute timeout between reads. Set 60-minute timeout between writes. Similarly, it is not uncommon to have a load balancer, such as HAProxy, in front of one or more Nginx servers Not surprisingly, we need to apply similar explicit configuration here as well e g for HAProxy.60-minute inactivity timeout for tunnels. The gotcha with the prece ding example is the extra tunnel timeout In HAProxy the connect client and server timeouts are applied only to the initial Upgrade handshake, but once the upgrade is complete, the timeout is controlled by the tunnel value. Nginx and HAProxy are just two of hundreds of different servers, proxies, and load balancers running in our data centers We can t enumerate all the configuration possibilities in these pages The previous examples are just an illustration that most infrastructure requires custom configuration to handle long-lived sessions Hence, before implementing application keepalives, double-check your infrastructure first. Long-lived and idle sessions occupy memory and socket resources on all the intermediate servers Hence, short timeouts are often justified as a security, resource, and operational precaution Deploying WebSocket, SSE, and 2 0, each of which relies on long-lived sessions, brings its own class of new operational challenges. Performance Checklist. Deploying a high-perfo rmance WebSocket service requires careful tuning and consideration, both on the client and on the server A short list of criteria to put on the agenda. Use secure WebSocket WSS over TLS for reliable deployments. Pay close attention to polyfill performance if necessary. Leverage subprotocol negotiation to determine the application protocol. Optimize binary payloads to minimize transfer size. Consider compressing UTF-8 content to minimize transfer size. Set the right binary type for received binary payloads. Monitor the amount of buffered data on the client. Split large application messages to avoid head-of-line blocking. Leverage other transports where applicable. Last, but definitely not least, optimize for mobile Real-time push can be a costly performance anti-pattern on mobile handsets, where battery life is always at a premium That s not to say that WebSocket should not be used on mobile To the contrary, it can be a highly efficient transport, but make sure to account for its requirements. Wit h Safari, you learn the way you learn best Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more. No credit card required. Websockets 101.written on Monday, September 24, 2017.Out of curiosity I taught the Fireteam presence server websockets as a protocol in addition to the proprietary protocol it speaks out of the box I don t really have a usecase for websocket per-se with the server, but I thought it might make it more useful for customers that want to use the event based parts of the API with HTML5 games This post focuses on implementing websockets on the server, not so much about how you would use them from the client and basically collects all thing I wish I would have known before. What are Websockets. So let s start with that part first What are websockets and why would you use websockets Basically only if you want to have a bidirectional communication between an actual web browser and some server Websocket is not necessarily a good protocol if neither of the endpoints is an actual browser Websockets suffer a lot under the restrictions and implementation details that were forced upon the protocol to make it work with existing infrastructure. Websockets in the current iteration as specified by RFC 6455 do a bunch of things differently to what a raw TCP connections does The name websocket gives the impression that it s a traditional socket In practice it combines the parts of UDP and TCP it s message based like UDP, but it s reliable like TCP So assuming you know what TCP is, here is what websocket adds on top of that. it upgrades from 1 1 through a system previously defined as part of the specification upgrade header. it sends the origin domain in the upgrade so that connections can be restricted to prevent CSRF attacks This works similar to CORS for. Through the handshake it becomes feasible to proxy the connection without losing information a proxy could inject an X-Real-IP or X-Forwarded-For header. It sends mes sages Each message can also carry control information and is wrapped in a frame. Messages sent from the client to the server are obfuscated with a basic transmission mask of 4 bytes which is sent within each websocket package Messages can be of utf-8 text type or binary nature. It adds an agreed way for the two peers to signal that the connection is about to be terminated that does not rely on the underlying TCP connection. Builtin heartbeating support That s actually pretty nifty because the application code in the browser does not have to deal with keeping the connection alive and can just assume that either the server or the browser will make sure that they exchange ping pongs. When to use them. Websockets make you sad There, I said it What started out as a really small simple thing ended up as an abomination of what feels like needles complexity Now the complexity comes for a reason The protocol went through many iterations and basically had to be changed multiple times because of unfor eseen security problems that came up with misbehaving proxies The protocol I created for the internal communication of our server is upgrading from just like websockets do, but without the secure parts And here is why it does not matter. Everybody knows about proxies We have proxies that do load balancing on the application side, we have proxies that do SSL offloading, we have proxies for all kinds of things Unfortunately outside our internal infrastructure everyone of us also has to deal with proxies in corporate networks, and worse, on mobile network connections The amount of shitty middleware installed all around the world is just staggering And this pretty much has shown me that the only way you can do anything useful these days is by putting TLS on top of everything and just force people to stop with their shenanigans On O2 s mobile networks you cannot use websockets unless they are encrypted You cannot get websocket connections through Amazon s ELB Their load balancer Heck, you ca n t even get PATCH as an method through the ELB. Everything that Fireteam will be doing will most likely always be behind an encrypted connection It guarantees me that nothing can do funny things with the data I m sending around And as a positive side effect I don t have to mask my communication like websocket does because I know the software stack on my side until it hits the internet The communication gets encrypted and I know nobody is going to change my data on the way to the client. In fact, I would also recommend to always use websockets through TLS Even if you don t care about the security side of things you will still benefit from the fact that your websocket connections succeed in many more cases Not encrypting your connection is definitely something you will regret sooner or later. The Handshake. Alright After this fairly long disclaimer you re still there, which probably means you still want to do websockets Fair enough Now let s start with the basics, the handshake This is wher e everything starts It upgrades your connection from to something else For the internal protocol we recommend to customers we upgrade our connection basically to a raw TCP connection Websockets are not an upgrade to TCP, it s an upgrade to a message based communication. To begin why would you upgrade from instead of directly starting with TCP as a protocol The reasons for why Fireteam s protocol starts with not all that different from why websockets upgrade from. Websockets upgrade from because it was believed that people would develop servers that serve both websocket connections as well as ones I don t believe for a second that this will be what people do at the end of the day however A server that handles stateless requests to answer with a reply has a very different behavior than a server that keeps TCP connections open However the advantage is that websockets use the same ports as and do and that is a huge win It s a win because these are privileged ports 1024 and they are tradition ally handled differently than non privileged ports For instance on a linux system only root can open such ports Even more important ELB only lets you open a handful of these privileged ports 25, 80 and 443 to be exact Since ELB also does socket level load balancing you can still do websockets on Amazon, just not through their local balancer. We re handling our persistent presence protocol very differently than our webservice but we still benefit from the upgrade in some edge cases That s mainly where we have to tunnel our communication through a library because arbitrary socket connections are not possible for security or scalability reasons If you have ever used Google Appengine or early Windows Phone you will have noticed that connections are possible where regular socket connections are not. You will also see that many corporate networks only allow certain ports outgoing The fact that websockets use the same port as make this much more interesting If anyone has ever used the flash soc ket policy system will know that pain Currently it s entirely impossible to use flash sockets behind Amazon s ELB because the Flash VM will attempt to connect to port 843 to get authorization information That s a port you can t open on the ELB So the idea of starting with is pretty solid. always supported upgrades, but unfortunately many proxies seem to have ignored that part of the specification The main reason for that probably is that until websockets came around nobody was actually using the Upgrade flag There was an SSL upgrade RFC that used the same mechanism but I don t think anyone is using that. Alright So what does the handshake look like The upgrade is initiated by the client, not by the server The way Fireteam upgrades the connection is by following the old SSL RFC and looks like this. The server then replies by upgrading. If the upgrade header was missing, the server instead answers with 426 Upgrade Required. What s interesting about this is that the upgrade require status code is defined, but it does not show up in the RFC Instead if does come from that SSL RFC. Websockets upgrade very similar, but they are using 400 Bad Request to signal a missing upgrade They also transmit a special key with the upgrade request which the server has to process and send back Th is is done so that a websocket connection cannot be established with an endpoint that is not aware of websockets Here is what the handshake looks like for the client. The websocket key here are random bytes The server takes these bytes and appends the special string 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 to it, then creates the SHA1 hash from it and base64 encodes the result the bytes, not the hexadecimal representation The magic string looks like a UUID and also is one, but that s completely irrelevant because the exact string needs to be used A lowercase representation or braces around the string would obviously fail That value is then put into the Sec-WebSocket-Accept header When the server has computed the value it can send an upgrade response back. The handshake can also include a protocol request and the websocket version information but you can t include arbitrary other headers If you compare the websocket upgrade with our own upgrade you will notice that we can t transmit the autho rization information There are two ways around that You can either transmit the authorization information as the first request or put it into the URL as query parameter. Also notice that the Sec-WebSocket-Accept header brings it s own grammar for the value Normally you would expect you can quote the value but the specification specifically requires a base64 value there. Websocket URLs. Alright As if websockets were not painful enough as they are, someone had the amazing idea to also introduce a new URL scheme Two in fact ws and wss Sounds like a tiny change from to but unfortunately that s not the case URLs have scheme specific grammar For instance FTP URLs can have authorization information in the netloc part ftp username server whereas can t mailto URLs don t have the leading slashes etc Websocket URLs are special in that they do not support anchors foo Now why would that matter It matters because whoever created the URL parsing module in Python also decided that they should stick as cl osely as possible to the strict standard that you cannot throw arbitrary URLs at the module For instance if you would try to parse websocket URLs you quickly realize that the results are just wrong. The reason why websockets have a separate URL is beyond me I suspect it stems from the fact that the RFC hints towards eventually dropping the upgrade from so the URL would not make much sense In any case it s just a very annoying example of where we now have to things now that were previously unnecessary. Also since it s a different protocol, protocol relative links will obviously not work You will have to switch between wss and ws by hand. Otherwise the same rules as for style URLs apply Namely that ws is unencrypted and has port 80 as default port and wss requires TLS encryption and port 443 as default. Authorization and IPs. Before we dive further into websockets let me throw yet another problem at you Since proxying is a word that comes up with websockets so very often we should probably ta lk about how proxies work there in the original RFC does not really talk much about TCP and IP addresses don t show up in there either However it has become clear over the last couple of years that there is a lot of value behind knowing which IP address connects to your server Traditionally this is doing by looking at the IP address that is stored in the individual IP packets Unfortunately this falls short the moment you start proxying through another server. There are two headers that have become popular to remedy that situation The first one is X-Forwarded-For which can contain one or multiple IPs of servers that took part in the request Each proxy server would add the remote address of the request to the header So if you have a user agent at 192 168 0 100 connect to 192 168 0 200 which acts as a proxy for 192 168 0 201 you end up with an X-Forwarded-For of 192 168 0 100 Bring in yet another proxy server that one would append it s own IP address to that list. Now there has to be a limi t to this Usually what you do is you configure the first server to reject any already set X-Forwarded-For headers or users can just use a browser extension or a proxy to inject a forged value in there And people do that I remember that people did exactly that to get American streaming content available in Europe by just injecting an American IP into that header. With websockets it s worse Odds are that your frontend proxy is doing TCP level proxying If it would be doing level load balancing and it would understand the Upgrade header it you could make it inject an X-Forwarded-For header and then read that on the server However Amazon s ELB as mentioned only works with websockets if you set it to TCP level proxying for instance And with that you lose your remote address Maybe not a problem for you, it definitely is a problem for us Now I know that protocols exists to inform a peer about the IP address on the other side of a proxy connection, but ELB does not speak it so it s a rather unin teresting thing for me. The way our server works is pretty similar to how the juggernaut server used to work You connect to a presence server that holds your socket connection open and acts as a central hub that uses other means to communicate with backend services We have a pretty lightweight server and we don t want to make it too complicated to authorize requests against it Namely we don t want to implement OAuth a second time for that server when we already use it for the strictly request response based webservice infrastructure. The trick we use for that is that we let a user authorize against the webservice infrastructure through OAuth and then call an endpoint that gives you a ticket that is valid for a few seconds That ticket is stored in redis It contains your account ID and a few important internal attributes, but we also store the IP on it which you used at the time the ticket was generated. With that ticket you go to the presence server and redeem it The presence server only n eeds to connect to redis and check if such a ticket exist and delete it Since we already use redis anyways in that server it s a pretty simple undertaking We obviously assume here that nobody takes the ticket between IP addresses We can t gurantee that this does not happen but we don t care about the implications either Someone could obviously create the ticket through a VPN and then disable the VPN connection when it s time to connect to the presence server But to be honest I don t care It s as far as I am concerned, no security problem. In theory the spec says you can also use any of the authorization systems basic auth, cookies etc but since you can t customize the headers with the JavaScript API that are being sent with the handshake you are basically very limited to implicit auth or auth through one of the first requests URL based. Now that we know how we can connect to the websocket server, how to upgrade to the websocket protocol and how authorization can be handled without losing the IP address information even if we do TCP level load balancing The next thing you have to know is how websocket transfer works As mentioned earlier websocket is not a stream based protocol like TCP, it s message based What s the difference With TCP you send bytes around and have to make sure for the most part that you can figure out the end of a message Our own protocol makes this very easy because we send full JSON objects around which are self terminating For naive JSON parsers like the one in the Python standard library that cannot parse of a stream we also add a newline at the end and ensure that all newlines in JSON strings are escaped So you can just read to the newline and then hand that line to the JSON parser. Websockets makes this easier because it puts a frame around everything Upside easier to handle from the JavaScript side, downside much harder to handle on the server side because you now need to wrap everything in frames. So let s have a look first how the frames are d efined This is what the RFC provides us with. Good news first as of the websocket version specified by the RFC it s only a header in front of each packet The bad news is that it s a rather complex header and it has the frighting word mask in it Here are the individual parts explained. fin 1 bit indicates if this frame is the final frame that makes up the message Most of the time the message fits into a single frame and this bit will always be set Experiments show that Firefox makes a second frame after 32K however. rsv1 rsv2 rsv3 1 bit each it wouldn t be a proper protocol if it did not include reserved bits As of right now, they are unused. opcode 4 bits the opcode Mainly says what the frame represents The following values are currently in use.0x00 this frame continues the payload from the last.0x01 this frame includes utf-8 text data.

No comments:

Post a Comment