WebSocket: kapcsolatfelépítés, keretek és kétirányú üzenetek
Célok
A lecke végére el tudod magyarázni a WebSocket kapcsolatfelépítését, a keretek és üzenetek szerepét, a maszkolás célját, a kontrollkereteket, és meg tudod mondani, mit nem ad a protokoll.
Miért kell?
Az eddigi módszerek vagy kérésenként új csere (polling, long polling), vagy egyirányú folyam (SSE). Ha mindkét fél gyakran kezdeményez, ugyanazon a kapcsolaton célszerű kétirányú üzeneteket váltani. Az MDN szerint a WebSocket API lehetővé teszi, hogy kétirányú interaktív kommunikációs munkamenetet lehessen nyitni a böngésző és a szerver között anélkül, hogy a válaszhoz lekérdezni kellene.
Kapcsolatfelépítés (handshake)
A kapcsolat HTTP-kéréssel indul, amelyben a kliens protokollváltást kér. Az RFC 6455 szerint a kérés GET, legalább HTTP/1.1, és tartalmazza az Upgrade: websocket és a Connection: Upgrade fejlécet, egy véletlenül választott Sec-WebSocket-Key kulcsot és a Sec-WebSocket-Version: 13 értéket; böngészőből az Origin is megjelenik. A szerver 101 Switching Protocols válaszban elfogadja, és a Sec-WebSocket-Accept értéket úgy számolja, hogy a kulcshoz egy rögzített GUID-ot (258EAFA5-E914-47DA-95CA-C5AB0DC85B11) fűz, SHA-1 lenyomatot készít, majd base64-kódolja. Az RFC példakulcsával (dGhlIHNhbXBsZSBub25jZQ==) az eredmény s3pPLMBiTxaQ9kYGzzhZRbK+xOo=.
sequenceDiagram
participant C as Böngésző
participant P as Reverse proxy
participant S as WebSocket-szerver
C->>P: GET + Upgrade: websocket
P->>S: Handshake továbbítása
S-->>P: 101 Switching Protocols
P-->>C: Kapcsolat létrejött
C->>S: Üzenet
S->>C: Üzenet
A ws séma titkosítatlan, a wss TLS-sel védett kapcsolatot jelent; az RFC szerint az alapértelmezett portok a 80 és a 443. Az MDN szerint a böngészők általában biztonságos kapcsolatot követelnek, és a nem szokásos portok gondot okozhatnak tűzfalaknál és proxyknál.
HTTP/2-n és HTTP/3-on a felépítés más: az RFC 8441 az „extended CONNECT” módszerrel (:protocol pszeudo-fejléc, SETTINGS_ENABLE_CONNECT_PROTOCOL beállítás) viszi át a WebSocketet egyetlen HTTP/2-folyamra, az RFC 9220 pedig ugyanezt adaptálja HTTP/3-ra. Ilyenkor nincs Upgrade és 101. A proxy és a szerver támogatását ellenőrizni kell.
Keretek és üzenetek
A protokoll keretekkel (frame) viszi az adatot; egy alkalmazási üzenet több keretre is bontható (fragmentáció). Szöveges (UTF-8) és bináris üzenetek küldhetők. A böngészői API üzenetes felületet ad, így nem kell az érkező bájtfolyamot saját keretezéssel darabolni, mint egy nyers TCP-protokollnál.
Maszkolás. Az RFC 6455 szerint a kliensnek minden elküldött keretet maszkolnia kell, a szervernek pedig nem szabad, és a szervernek le kell zárnia a kapcsolatot, ha maszkolatlan keretet kap. A maszkolás célja az RFC 10.3 szerint a közbenső proxyk gyorsítótárának megmérgezése elleni védelem: a távoli szkript ne tudja uralni, hogyan jelenik meg az adat a vezetéken. Nem titkosítás; a bizalmasságot és az integritást a TLS (wss) adja (RFC 10.6).
Kontrollkeretek. A Close (lezárás), a Ping és a Pong keretek legfeljebb 125 bájt hasznos adatot vihetnek, és nem darabolhatók. A Ping-re a másik félnek Pong-gal kell válaszolnia, amely a Ping adatát visszhangozza; ez életjelzésre és a kapcsolat ellenőrzésére használható. A rendezett lezárásnál a Close keret állapotkódot hordozhat: az RFC szerint az 1000 a normál lezárás, az 1001 a „távozás” (például szerverleállás vagy oldalelhagyás), az 1006 pedig fenntartott érték, amelyet nem küldenek, és azt jelzi, hogy a kapcsolat Close keret nélkül, rendellenesen szűnt meg. A böngészői JavaScript WebSocket API nem ad közvetlen Ping-küldő metódust, ezért szükség esetén alkalmazási szintű heartbeatet kell használni (10.3).
Alprotokoll
Az RFC szerint a kliens a Sec-WebSocket-Protocol fejlécben sorolhatja fel a támogatott alprotokollokat, a szerver pedig egyet választ ki (vagy egyet sem), és visszaküldi. Az alprotokoll megnevezi az üzenetformátumot és a szabályrendszert. A WebSocket maga nem definiálja, mi a „belépés”, a „feliratkozás” vagy a „foglalás”: ezt az alkalmazási üzenetséma írja le (10.2).
Jellemzők
Szempont
WebSocket
Irány
Kétirányú
Kezdeményező
A kapcsolatot a kliens nyitja; utána bármelyik fél küldhet
Kapcsolat tartóssága
Tartós, amíg bármelyik fél vagy a hálózat meg nem szakítja
Késleltetés
Alacsony: nincs kérésenkénti fejléc és kapcsolatfelépítés
Terhelés
Nyitott kapcsolat per kliens (memória, fájlleíró); alacsony üzenetenkénti költség
Hibatűrés
A megszakadást és az üzenetvesztést az alkalmazásnak kell kezelnie (10.3)
Mikor jó?
Gyakori kétirányú üzenetváltás: közös szerkesztés, chat, vezérlés, játék
Mikor nem?
Ritka, csak szerver felől érkező értesítés (SSE vagy polling egyszerűbb); gyorsítótárazható erőforrás-olvasás
Gyakori tévhitek
Állítás
Pontosítás
„A WebSocket egy HTTP-kapcsolat.”
HTTP-kéréssel indul, de utána saját keretezésű protokoll.
„A maszkolás titkosít.”
Nem; a bizalmasságot a TLS (wss) adja.
„A WebSocket mindig 101-gyel indul.”
HTTP/2-n és HTTP/3-on extended CONNECT az alap.
„Nyitott kapcsolat = sikeres művelet.”
A transport és az alkalmazási állapot külön.
Röviden
A WebSocket HTTP-kéréssel indul, protokollt vált (HTTP/1.1: 101), majd keretekkel visz üzeneteket.
A kliens minden keretet maszkol; ez nem titkosítás.
A kontrollkeretek (Ping/Pong/Close) életjelet és rendezett lezárást adnak.
Az üzenetek jelentését és a tartósságot az alkalmazásnak kell kitalálnia.
Ellenőrző kérdések
Mit biztosít a WebSocket, és mit kell az alkalmazásnak definiálnia?
Miért nem titkosítás a maszkolás?
Miért nem bizonyít sikeres műveletet a kapcsolat nyitott állapota?
WebSocket: kapcsolatfelépítés, keretek és kétirányú üzenetek
Célok
A lecke végére el tudod magyarázni a WebSocket kapcsolatfelépítését, a keretek és üzenetek szerepét, a maszkolás célját, a kontrollkereteket, és meg tudod mondani, mit nem ad a protokoll.
Miért kell?
Az eddigi módszerek vagy kérésenként új csere (polling, long polling), vagy egyirányú folyam (SSE). Ha mindkét fél gyakran kezdeményez, ugyanazon a kapcsolaton célszerű kétirányú üzeneteket váltani. Az MDN szerint a WebSocket API lehetővé teszi, hogy kétirányú interaktív kommunikációs munkamenetet lehessen nyitni a böngésző és a szerver között anélkül, hogy a válaszhoz lekérdezni kellene.
Kapcsolatfelépítés (handshake)
A kapcsolat HTTP-kéréssel indul, amelyben a kliens protokollváltást kér. Az RFC 6455 szerint a kérés
GET, legalább HTTP/1.1, és tartalmazza azUpgrade: websocketés aConnection: Upgradefejlécet, egy véletlenül választottSec-WebSocket-Keykulcsot és aSec-WebSocket-Version: 13értéket; böngészőből azOriginis megjelenik. A szerver101 Switching Protocolsválaszban elfogadja, és aSec-WebSocket-Acceptértéket úgy számolja, hogy a kulcshoz egy rögzített GUID-ot (258EAFA5-E914-47DA-95CA-C5AB0DC85B11) fűz, SHA-1 lenyomatot készít, majd base64-kódolja. Az RFC példakulcsával (dGhlIHNhbXBsZSBub25jZQ==) az eredménys3pPLMBiTxaQ9kYGzzhZRbK+xOo=.A
wsséma titkosítatlan, awssTLS-sel védett kapcsolatot jelent; az RFC szerint az alapértelmezett portok a 80 és a 443. Az MDN szerint a böngészők általában biztonságos kapcsolatot követelnek, és a nem szokásos portok gondot okozhatnak tűzfalaknál és proxyknál.HTTP/2-n és HTTP/3-on a felépítés más: az RFC 8441 az „extended CONNECT” módszerrel (
:protocolpszeudo-fejléc,SETTINGS_ENABLE_CONNECT_PROTOCOLbeállítás) viszi át a WebSocketet egyetlen HTTP/2-folyamra, az RFC 9220 pedig ugyanezt adaptálja HTTP/3-ra. Ilyenkor nincsUpgradeés101. A proxy és a szerver támogatását ellenőrizni kell.Keretek és üzenetek
A protokoll keretekkel (frame) viszi az adatot; egy alkalmazási üzenet több keretre is bontható (fragmentáció). Szöveges (UTF-8) és bináris üzenetek küldhetők. A böngészői API üzenetes felületet ad, így nem kell az érkező bájtfolyamot saját keretezéssel darabolni, mint egy nyers TCP-protokollnál.
Maszkolás. Az RFC 6455 szerint a kliensnek minden elküldött keretet maszkolnia kell, a szervernek pedig nem szabad, és a szervernek le kell zárnia a kapcsolatot, ha maszkolatlan keretet kap. A maszkolás célja az RFC 10.3 szerint a közbenső proxyk gyorsítótárának megmérgezése elleni védelem: a távoli szkript ne tudja uralni, hogyan jelenik meg az adat a vezetéken. Nem titkosítás; a bizalmasságot és az integritást a TLS (
wss) adja (RFC 10.6).Kontrollkeretek. A Close (lezárás), a Ping és a Pong keretek legfeljebb 125 bájt hasznos adatot vihetnek, és nem darabolhatók. A Ping-re a másik félnek Pong-gal kell válaszolnia, amely a Ping adatát visszhangozza; ez életjelzésre és a kapcsolat ellenőrzésére használható. A rendezett lezárásnál a Close keret állapotkódot hordozhat: az RFC szerint az 1000 a normál lezárás, az 1001 a „távozás” (például szerverleállás vagy oldalelhagyás), az 1006 pedig fenntartott érték, amelyet nem küldenek, és azt jelzi, hogy a kapcsolat Close keret nélkül, rendellenesen szűnt meg. A böngészői JavaScript WebSocket API nem ad közvetlen Ping-küldő metódust, ezért szükség esetén alkalmazási szintű heartbeatet kell használni (10.3).
Alprotokoll
Az RFC szerint a kliens a
Sec-WebSocket-Protocolfejlécben sorolhatja fel a támogatott alprotokollokat, a szerver pedig egyet választ ki (vagy egyet sem), és visszaküldi. Az alprotokoll megnevezi az üzenetformátumot és a szabályrendszert. A WebSocket maga nem definiálja, mi a „belépés”, a „feliratkozás” vagy a „foglalás”: ezt az alkalmazási üzenetséma írja le (10.2).Jellemzők
Gyakori tévhitek
wss) adja.101-gyel indul.”Röviden
101), majd keretekkel visz üzeneteket.Ellenőrző kérdések
Források