Компьютерные сети
WebSocket: двусторонняя связь
HTTP похож на почту: клиент отправляет письмо, ждёт ответа. Но что если сервер хочет написать первым? WebSocket - это телефонный звонок: линия открыта, говорите когда хотите.
- **Slack/Discord** - миллионы WebSocket-соединений для мгновенных сообщений
- **Биржевые терминалы** - котировки обновляются 10-100 раз в секунду через WebSocket
- **Figma/Google Docs** - курсоры других пользователей и изменения в реальном времени
Предварительные знания
Зачем нужен WebSocket
HTTP создан для запрос-ответ: клиент спрашивает, сервер отвечает. Но что если серверу нужно отправить данные клиенту без запроса? Биржевые котировки, сообщения в чате, позиция игрока - всё это требует **push от сервера**.
**WebSocket** (RFC 6455) - протокол полнодуплексной связи поверх TCP. Одно соединение, данные в обе стороны в любой момент. Идеально для real-time приложений.
WebSocket использует тот же порт, что и HTTP (80/443), и начинается с HTTP-запроса. Это позволяет проходить через прокси и файрволы. После установки соединения HTTP "уступает место" - дальше идёт бинарный протокол WebSocket.
Какую проблему HTTP решает WebSocket?
Upgrade Handshake: переключение протокола
WebSocket-соединение начинается с обычного HTTP-запроса. Клиент отправляет заголовок `Upgrade: websocket`, и если сервер согласен - отвечает статусом **101 Switching Protocols**. После этого TCP-соединение переключается на протокол WebSocket.
**Sec-WebSocket-Key/Accept** - механизм защиты от случайного подключения. Клиент отправляет случайный ключ, сервер конкатенирует его с magic string и возвращает SHA-1 хэш. Это не шифрование, а проверка, что обе стороны понимают протокол.
После handshake TCP-соединение остаётся открытым. Обе стороны могут отправлять **фреймы** (frames) - небольшие пакеты данных с минимальным заголовком. Соединение живёт, пока одна из сторон не закроет его или не произойдёт разрыв.
Какой HTTP-статус означает успешный переход на WebSocket?
WebSocket Frames: структура данных
После handshake данные передаются **фреймами**. Каждый фрейм имеет заголовок (2-14 байт) и payload. Типы фреймов: текстовые (UTF-8), бинарные, управляющие (ping/pong/close).
**Маскировка (masking)** - клиент обязан маскировать payload с помощью 4-байтового ключа. Это защита от cache poisoning атак через прокси. Сервер отправляет данные без маскировки.
Большие сообщения можно разбить на несколько фреймов (fragmentation). FIN=0 означает "продолжение следует", FIN=1 - последний фрейм. Это позволяет стримить данные без буферизации всего сообщения.
Почему клиент обязан маскировать payload в WebSocket?
Применение WebSocket и альтернативы
WebSocket идеален для сценариев с частыми двусторонними обновлениями. Но не каждое real-time приложение требует WebSocket - иногда SSE или даже polling достаточно.
**Server-Sent Events (SSE)** - односторонний push от сервера через HTTP. Проще WebSocket, автоматический reconnect, но только server→client. Для чата не подойдёт, для уведомлений - отлично.
**Socket.IO** - популярная библиотека, которая абстрагирует транспорт. Она пытается использовать WebSocket, но автоматически fallback на long-polling если WS недоступен. Добавляет комнаты, broadcasting, reconnect.
**WebTransport** - новый стандарт для real-time в браузере поверх HTTP/3 (QUIC). Поддерживает unreliable datagram (как UDP) и множество потоков. Для игр и видео может заменить WebSocket.
WebSocket всегда лучше HTTP для real-time приложений
WebSocket добавляет сложность (state, reconnect, scaling). Для простых push-уведомлений SSE проще и надёжнее
WebSocket требует управления соединениями на сервере, что усложняет горизонтальное масштабирование. SSE работает поверх HTTP и легко проходит через CDN, прокси, load balancer. Выбирайте технологию под задачу: SSE для push, WebSocket для full-duplex.
Для какого сценария SSE подходит лучше, чем WebSocket?
Итоги
- **WebSocket** - full-duplex протокол поверх TCP, начинается с HTTP Upgrade (статус 101)
- **Фреймы** - минимальный overhead (2-14 байт), маскировка обязательна для клиента, типы: text/binary/control
- **Альтернативы** - SSE для односторонних push, Socket.IO для абстракции, WebTransport для UDP-like в браузере
Связанные темы
WebSocket строится на HTTP и используется в современной инфраструктуре:
- HTTP основы — WebSocket начинается с HTTP Upgrade request
- Load Balancing — WebSocket-соединения требуют sticky sessions или специальной балансировки
Вопросы для размышления
- Почему WebSocket использует HTTP для начального handshake, а не собственный протокол?
- Какие проблемы возникают при масштабировании WebSocket-серверов горизонтально?
- В каком случае вы бы выбрали long polling вместо WebSocket?