WebSocket

**WebSocket** on arvutitevaheline andmevahetusprotokoll, mis võimaldab täisdupleksandmevahetust ühe TCP-ühenduse kaudu. WebSocketi protokolli standardiseeris 2011. aastal internetiehituse töörühm (IETF) kommentaarinõudes 6455.

WebSocket ühildub hüperteksti edastusprotokolliga (HTTP), kasutades kätlusel HTTP Upgrade päist, et HTTP pealt WebSocketi protokollile lülituda.

Enamus brauseritest toetab WebSocketi protokolli, sealhulgas Google Chrome, Microsoft Edge, Internet Explorer, Firefox, Safari ja Opera.

## Ülevaade
WebSocketi protokoll võimaldab kliendil, tavaliselt brauseril või ka muul rakendusel, serveriga andmeid vahetada efektiivsemalt kui pooldupleks alternatiivid nagu HTTP pikk kutsumine (ingl *long polling*). Reaalaegse andmeside saavutamiseks standardiseeriti viis, et server saaks kliendile andmeid saata ilma, et klient neid eelnevalt pärima peaks. Sama kehtib ka vastupidi, luues kahesuunalise sõnumivahetuse, kuni ühendus on avatud. Sõnumivahetus toimub tavaliselt üle TCP pordi 433 (80 ebaturvaliste ühenduste korral), mis on kasuks keskkondades, kus muud ühendused on tulemüüri poolt keelatud.

TCP ühendus iseseisvalt edastab voona vaid baite ilma viisita otseselt sõnumite edastamiseks. WebSocketi spetsifikatsioon defineerib kaadrid, mida saab kasutada standardiseeritult sõnumite edastamiseks ja lugemiseks. Spetsifikatsioon defineerib ühenduste tähistamiseks ka kaks ühtset ressursiidentifikaatori (URI) skeemi: `ws` (WebSocket) ja `wss` (WebSocket Secure), vastavalt krüpteerimata ja krüpteeritud ühendusteks. Skeemi nimetuse ja ankru (ehk`#`ei toetata) väliselt jälgivad URI muud osad üldist URI süntaksit.

Websocketi kätlust ja kaadreid on võimalik lähemalt uurida kasutades brauseri arendustööriistu.

## Ajalugu
Esmaselt mainiti WebSocketit kui TCPConnection HTML5 spetsifikatsioonis mõne TCP põhise sokli rakendusliidese ajutise kohatäitjana. Esimene versioon protokollist sündis Michael Carteri 2008. aasta juunis alustatud aruteludest. Nimetuse "WebSocket" mõtlesid välja Ian Hickson ja Michael Carter pärast lühidat koostööd #whatwg IRC jututoas. 2009. aasta detsembris avaldatud Google Chrome 4 oli esimene brauser, millel oli WebSocket implementeeritud ja vaikimisi kasutusel. Protokolli arendasid kuni 2010. aasta veebruarini W3C ja WHATWG ja hiljem juba IETF, kus Ian Hickson avaldas veel kaks täiendust.

Pärast protokolli avaldamist ja mitme brauseri poolt implementeerimist, avaldas Ian Fette 2011. aasta detsembris lõpliku kommentaarinõude.

## Veebiserverite implementatsioon
NginX toetab WebSocketi protokolli alates versioonist 1.3.14 mis avaldati aastal 2013.  

## Protokolli kätlus
WebSocket ühenduse loomiseks saadab klient serverile kätluse päringu, millele server vastab kätluse vastusega.

Kliendi päring:
```http
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
```
Serveri vastus:
```http
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
```
Kätlus algab HTTP päringu ja vastusega, mis nõuab serveri valmidust samal pordil nii HTTP kui WebSocket ühenduste haldamist. Kui ühendus on loodud, vahetub ühendus kahesuunaliseks WebSocketi protokollile, mis enam ei ühildu HTTP protokolliga.

Lisaks `Upgrade` päisele saadab klient `Sec-WebSocket-Key` päise, mis sisaldab base64 kodeeritud juhuslikke baite, ning server vastab sama võtme räsiga `Sec-WebSocket-Accept` päises. Selle eesmärk ei ole tagada turvalisust, privaatsust või terviklikkust, vaid vältida vahemälu talletava proksiserveri poolt vana vastuse tagastamist ilma uue ühenduse loomiseta. Räsifunktsioon liidab `Sec-WebSocket-Key` päise väärtusele UUID sõne `258EAFA5-E914-47DA-95CA-C5AB0DC85B11` , rakendab sellel SHA-1 räsifunktsiooni ja tagastab tulemuse base64 kodeeringus.

Pärast ühenduse loomist saavad klient ja server mõlemas suunas vahetada nii andmete kui teksti kaadreid. Andmete kaader on minimaalne, sisaldades väikest päist ja sisu. WebSocketi andmeedastusi kutsutakse "sõnumiteks", milles üks sõnum võib valikuliselt olla jaotatud mitmesse edastatud kaadrisse. Tulenevalt on võimalik saata sõnumeid, kus andmete algus on olemas, kuid terve sõnumi pikkus on teadmata, edastades järjestikuselt mitu kaadrit kuni jõutakse lõpuni, mis on tähistatud lõpetusbitiga. Protokolli laiendamise korral on tänu sellele võimalik ka mitut voogu multipleksida, näiteks et vältida olukorda kus üks suur edastus hõivab kogu sokli.

## Turvalisus
Erinevalt tavalistest domeenivahelistest HTTP päringutest ei ole WebSocketi päringud piiratud ühisallika poliitika (ingl. same-origin policy) poolt. Tulenevalt peab ühenduse loomise korral WebSocketi serveri pool valideerima päringu `Origin` päist lubatud allikate vastu, et vältida veebilehtedevahelist WebSocketi kaaperdamise ründeid (sarnane lehtedevahelisele päringu võltsimisele), mis võib osutuda võimalikuks kui ühendust autenditakse küpsistega või HTTP autentimisega. Tundlike andmete edastamise korral on mõistlikum kasutada lube või muid täiendavaid turvameetmeid et WebSocketi ühendust autentida. 

## Puhverserveri läbimine
WebSocketi protokolli kliendipoolsed implementatsioonid püüavad ühendamisel tuvastada kas kasutajaagent on seadistatud proksit kasutama, mille korral kasutatakse HTTP CONNECT-meetodit, et luua püsiv tunnel. WebSocketi protokoll üldiselt toimib läbipaistvate (ei muuda päringuid) puhverserveritega, kui krüpteeritud ühendust kasutada. Teistel juhtudel võib piisata puhverserveri ümberseadistamisest või vanemate serverite puhul uuenduste paigaldamisest. 

Krüpteeritud ühenduste korral tagab transpordikihi turbeprotokoll (TLS) HTTP CONNECT-meetodi kasutuse kui brauser on seadistatud konkreetset puhverserverit kasutama. Sellega luuakse tunnel, mis võimaldab kliendi ja serveri vahelist TCP andmesidet läbi puhverserveri. Läbipaistvate puhverserverite puhul ei tuvasta brauser puhverserverit ja HTTP CONNECT-meetodit ei rakendata. Krüpteeritud andmete korral võib aga puhverserver andmed lihtsalt läbi lubada. Krüpteeritud ühenduse kasutamine ei ole ressursside mõttes tasuta, kuid tagab suurima ühenduse õnnestumise tõenäosuse.

## Viited