Аутентификация и надёжность канала
Как понять, кто подключился, и как держать канал живым и надёжным.
Heartbeat (ping/pong) — периодический обмен служебными фреймами, чтобы убедиться, что соединение живо, и вовремя обнаружить «мёртвые» каналы.
Аутентификация при подключении
WebSocket не имеет привычных HTTP-заголовков на каждом сообщении — авторизуются один раз, при подключении. Обычно клиент передаёт токен. Способы: в query-параметре адреса (wss://host/chat?token=...), в первом сообщении после open, или через cookie (она уходит с рукопожатием). Сервер проверяет токен и либо принимает соединение, либо закрывает его с кодом ошибки.
{ "type": "auth", "token": "eyJhbGciOi..." }Пока клиент не прошёл аутентификацию, сервер не пускает его в комнаты и игнорирует прочие сообщения.
Heartbeat: жив ли канал
TCP может «тихо умереть»: провод выдернули, Wi-Fi отвалился — а сокет на сервере всё ещё числится открытым. Чтобы это ловить, стороны периодически шлют ping и ждут pong. Не пришёл pong за отведённое время — считаем соединение мёртвым и закрываем.
Сервер --ping--> Клиент
Сервер <--pong-- Клиент (ок, живой)
Сервер --ping--> Клиент
(pong не пришёл за 30 сек)
Сервер закрывает «мёртвое» соединениеПереподключение и потеря сообщений
Сети рвутся — клиент обязан переподключаться сам (или через Socket.IO). Правильный реконнект делает паузы с ростом (1с, 2с, 4с...), чтобы не долбить упавший сервер. Отдельная проблема — сообщения, пришедшие во время обрыва: их клиент пропустил. Решение — нумеровать сообщения и при реконнекте просить сервер: «дай всё после №42». Сервер берёт пропущенное из истории (из базы) и досылает.
Как работает под капотом
В протоколе WebSocket есть встроенные ping/pong-фреймы, и многие библиотеки шлют их сами. Но прикладной heartbeat (свой type: "ping") иногда удобнее: он точно проходит через все слои и виден приложению. Восстановление пропущенного опирается на то, что у сообщений есть монотонный номер (или метка времени), а история хранится отдельно от живого канала — поэтому даже после долгого обрыва клиент догоняет состояние.
Частые ошибки
- Класть токен в код и не проверять его на сервере. Аутентификацию всегда проверяет сервер, клиенту доверять нельзя.
- Реконнект без задержки и джиттера. Тысячи клиентов разом ударят по поднявшемуся серверу и снова уронят его.
- Игнорировать пропуски при обрыве. Без нумерации и догрузки часть сообщений потеряется молча.
Итоги
- WebSocket аутентифицируют один раз при подключении — токеном (query/первое сообщение/cookie).
- Heartbeat ping/pong обнаруживает «тихо умершие» соединения.
- Реконнект делают с нарастающей паузой; не штурмуйте упавший сервер.
- Пропущенные при обрыве сообщения догружают по номеру из истории в базе.