WebSocket — protokół pełnodupleksowej komunikacji, zapewniający stałe połączenie między klientem a serwerem do wymiany danych w czasie rzeczywistym. W przeciwieństwie do tradycyjnych żądań HTTP, ten protokół ustanawia jedno połączenie i wykorzystuje je do dwukierunkowej transmisji bez ponownych uzgodnień. Według danych Mozilla Developer Network (2025), WebSocket zmniejsza opóźnienia nawet o 50% w porównaniu z HTTP polling w aplikacjach czasu rzeczywistego.
Najważniejsze
WebSocket — to protokół komunikacji działający na TCP i zapewniający pełnodupleksowy kanał między klientem a serwerem. Został znormalizowany przez IETF jako RFC 6455 w 2011 roku i jest obsługiwany przez wszystkie nowoczesne przeglądarki, platformy mobilne i frameworki serwerowe.
W przeciwieństwie do HTTP, gdzie klient inicjuje żądanie i otrzymuje odpowiedź, WebSocket pozwala obu stronom wysyłać wiadomości w dowolnym momencie po nawiązaniu połączenia. To czyni go idealnym dla scenariuszy wymagających natychmiastowej dostawy danych: czaty, powiadomienia, współdzielone edytowanie dokumentów.
Protokół WebSocket używa portu HTTP 80 lub HTTPS 443 do początkowego uzgodnienia, po czym przełącza się na własny protokół z minimalnym nagłówkiem — zaledwie 2 bajty zamiast 800+ bajtów w HTTP. Ta cecha daje znaczną przewagę wydajnościową przy dużej liczbie wiadomości.
Połączenie WebSocket rozpoczyna się od żądania HTTP Upgrade, po czym protokół przełącza się na binarny format ramkowy. Rozmiar ramki waha się od 2 bajtów do 2^63 bajtów, co pozwala przesyłać zarówno krótkie wiadomości tekstowe, jak i duże dane binarne. Obsługiwana jest fragmentacja wiadomości, maskowanie danych od klienta do serwera oraz ping/pong do utrzymania połączenia.
Proces nawiązywania połączenia WebSocket składa się z dwóch etapów: uzgodnienie i transmisja danych. Na etapie uzgodnienia klient wysyła żądanie HTTP z nagłówkiem Upgrade: websocket, a serwer potwierdza przełączenie protokołu statusem 101 Switching Protocols. Następnie połączenie przechodzi w tryb pełnodupleksowej transmisji.
Każda wiadomość w WebSocket jest dzielona na ramki. Ramka zawiera opcode (tekst, dane binarne, zamknięcie, ping/pong), długość payloadu i klucz maskujący dla danych od klienta. Ramka może być fragmentowana — ramki kontrolne (ping/pong) mogą być przesyłane między fragmentami wiadomości, co zapobiega zrywaniu połączenia przy długiej transmisji.
const ws = new WebSocket('wss://example.com/chat')
ws.addEventListener('open', () => {
console.log('Połączenie nawiązane')
ws.send('Witaj, serwerze!')
})
ws.addEventListener('message', (event) => {
console.log('Otrzymano:', event.data)
})
ws.addEventListener('close', () => {
console.log('Połączenie zamknięte')
})
W powyższym przykładzie klient tworzy obiekt WebSocket, podając zabezpieczony URL wss://. Po otwarciu połączenia wysyłana jest wiadomość powitalna, a procedura obsługi message odbiera odpowiedzi od serwera. Przy zamknięciu uruchamia się procedura obsługi close — jest to ważne dla ponownego połączenia przy przerwie w sieci.
Główna różnica między WebSocket a HTTP polega na modelu interakcji. HTTP działa w schemacie żądanie-odpowiedź: klient inicjuje żądanie, serwer zwraca odpowiedź, połączenie jest zamykane. WebSocket natomiast ustanawia stały kanał, przez który obie strony mogą inicjować transmisję w dowolnym momencie.
Dla aplikacji wymagających niskiego opóźnienia i stałego strumienia danych, WebSocket jest znacznie wydajniejszy. HTTP Long Polling — alternatywa, w której serwer utrzymuje otwarte żądanie do czasu pojawienia się danych — tworzy nadmierne obciążenie serwera i zwiększa zużycie pamięci z powodu wielu jednoczesnych połączeń.
| Parametr | WebSocket | HTTP |
|---|---|---|
| Model | Pełnodupleksowy | Żądanie-odpowiedź |
| Nagłówek | 2–14 bajtów | 400–800 bajtów |
| Stałe połączenie | Tak, jedno | Nie, nowe na żądanie |
| Opóźnienie | Niskie (1–5 ms) | Wysokie (50–200 ms) |
| Protokół | ws:// lub wss:// | http:// lub https:// |
Według High Performance Browser Networking (Grigorik, O’Reilly), WebSocket zmniejsza opóźnienia sieciowe w scenariuszach czasu rzeczywistego o 40–60% w porównaniu z HTTP Long Polling, a obciążenie serwera spada 3–5 razy dzięki eliminacji ponownych uzgodnień.
Dzięki niskiemu opóźnieniu i dwukierunkowej komunikacji, WebSocket jest używany w szerokim spektrum aplikacji. Kluczowe scenariusze obejmują natychmiastową wymianę wiadomości, synchronizację stanu w grach i przesyłanie danych rynkowych w systemach finansowych.
WebSocket stał się standardem de facto dla aplikacji czatowych. Platformy takie jak Slack, Telegram Web i WhatsApp Web używają WebSocket do natychmiastowej dostawy wiadomości. Protokół pozwala wysyłać zarówno wiadomości tekstowe, jak i pliki przez jeden kanał, a mechanizm ping/pong utrzymuje połączenie aktywne nawet przy braku aktywności.
Wieloosobowe gry przeglądarkowe i mobilne wymagają minimalnego opóźnienia dla synchronizacji stanu graczy. WebSocket przesyła współrzędne, akcje i zdarzenia w czasie rzeczywistym bez opóźnień żądań HTTP. Frameworki takie jak Socket.IO i Colyseus abstrahują niskopoziomową pracę z protokołem, dodając automatyczne ponowne łączenie i pokoje.
Terminale giełdowe i platformy tradingowe używają WebSocket do otrzymywania notowań w czasie rzeczywistym. Opóźnienie rzędu kilku milisekund może kosztować miliony dolarów, dlatego API finansowe — na przykład Binance WebSocket Streams, Coinbase Pro — udostępniają właśnie interfejsy WebSocket dla danych rynkowych.
W rozwoju mobilnym WebSocket jest używany przez natywne API: URLSessionWebSocketTask na iOS i OkHttp WebSocket na Android. Dla Flutter istnieje biblioteka web_socket_channel, a dla React Native — react-native-websocket. Urządzenia IoT stosują WebSocket do przesyłania telemetrii i odbierania poleceń sterowania, ponieważ protokół zużywa mniej energii niż ciągłe HTTP-polling.
Rozpatrzmy przykład części serwerowej w Node.js z biblioteką ws — najpopularniejszą implementacją WebSocket dla JavaScript. Serwer przyjmuje połączenia, przetwarza wiadomości i transmituje je do wszystkich podłączonych klientów.
const WebSocket = require('ws')
const wss = new WebSocket.Server({ port: 8080 })
wss.on('connection', (ws) => {
console.log('Nowy klient podłączony')
ws.on('message', (data) => {
console.log('Otrzymano:', data.toString())
ws.send('Serwer otrzymał twoją wiadomość')
})
ws.on('close', () => {
console.log('Klient rozłączony')
})
})
console.log('Serwer WebSocket uruchomiony na porcie 8080')
Serwer tworzy instancję WebSocket.Server na porcie 8080 i oczekuje na połączenia. Każdemu nowemu klientowi przypisywany jest osobny obiekt ws, przez który serwer może wysyłać wiadomości indywidualnie. Transmisja wiadomości do wszystkich klientów realizowana jest przez masowe przejście przez tablicę połączeń. Przy dużej liczbie klientów (ponad 1000) zaleca się używanie bibliotek wspierających klastrowanie, takich jak Socket.IO, które dodają skalowanie przez Redis i automatyczne ponowne łączenie.
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send('Wiadomość dla wszystkich uczestników')
}
})
Sprawdzenie readyState przed wysłaniem jest obowiązkowe: jeśli klient już się rozłączył, wywołanie send spowoduje błąd. Flaga WebSocket.OPEN gwarantuje, że połączenie jest aktywne i wiadomość zostanie dostarczona.
Dla mobilnych aplikacji iOS WebSocket jest implementowany przez URLSessionWebSocketTask, dostępny od iOS 13. Sesja tworzy zadanie z URL protokołu wss://, po czym wywoływane są metody send i receive. Odbieranie wiadomości można zorganizować przez ciągłą rekurencję receive, która oczekuje na następną wiadomość po przetworzeniu poprzedniej, co zapewnia stały odbiór danych bez ponownego łączenia. Dla Androida używany jest OkHttp WebSocket, który udostępnia podobny interfejs z callbackami onOpen, onMessage, onClosing i onClosed, a także automatyczne ponowne łączenie przy zerwaniu połączenia.
Podczas pracy z WebSocket w aplikacjach mobilnych należy uwzględnić zarządzanie cyklem życia: gdy aplikacja przechodzi w tło, połączenie może zostać zerwane przez system. Na iOS należy ponownie nawiązywać połączenie przy powrocie na pierwszy plan przez delegata sceneDidBecomeActive. Na Android należy używać komponentów świadomych cyklu życia (Lifecycle-aware) lub Service do utrzymania połączenia. Dodatkowo zaleca się zaimplementowanie exponential backoff przy ponownym łączeniu — zwiększanie interwału między próbami z 1 do 30 sekund, aby nie tworzyć nadmiernego obciążenia serwera przy tymczasowych problemach sieci.
Często zadawane pytania
WebSocket ustanawia stałe pełnodupleksowe połączenie, przez które obie strony mogą wysyłać dane w dowolnym momencie. HTTP działa w schemacie żądanie-odpowiedź, gdzie każda wymiana wymaga nowego połączenia i pełnych nagłówków. WebSocket używa jednego kanału TCP i nagłówków tylko 2–14 bajtów, co radykalnie zmniejsza opóźnienia.
WebSocket używa portu 80 dla niezabezpieczonych połączeń (ws://) i portu 443 dla zabezpieczonych (wss://). Pozwala to przechodzić przez większość serwerów proxy i firmowych zapór sieciowych bez dodatkowej konfiguracji. Port 443 jest zalecany dla środowisk produkcyjnych ze względu na szyfrowanie TLS.
Tak, WebSocket jest obsługiwany na wszystkich platformach mobilnych. W iOS natywna klasa URLSessionWebSocketTask jest dostępna od iOS 13. W Android — klasa OkHttp WebSocket i standardowy java.net.WebSocket. Dla React Native istnieje biblioteka react-native-websocket.
WebSocket Secure — zabezpieczona wersja protokołu działająca na TLS. Wszystkie dane są szyfrowane tak samo jak w HTTPS. WSS jest obowiązkowy dla aplikacji produkcyjnych, szczególnie przy przesyłaniu tokenów uwierzytelniających lub danych osobowych przez WebSocket.
Główne alternatywy: HTTP Long Polling (serwer utrzymuje otwarte żądanie), Server-Sent Events (jednokierunkowy strumień z serwera) i WebRTC Data Channel (komunikacja peer-to-peer). Server-Sent Events są prostsze w implementacji, ale nie obsługują wysyłania od klienta do serwera.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również