Что такое WebSockets и как реализовать live-обновления на фронте и бэке
Современные веб-приложения требуют не только отображения статических данных, но и мгновенной реакции на изменения — будь то новые сообщения в чате, обновления курсов валют, уведомления или онлайн-игры. Классический HTTP-запрос «клиент → сервер» плохо подходит для подобных задач, ведь данные передаются только по инициативе клиента.
Здесь на помощь приходят WebSockets — технология, позволяющая устанавливать постоянное двунаправленное соединение между клиентом и сервером.
Как работают WebSockets
- При первом подключении клиент отправляет HTTP-запрос с заголовком Upgrade, предлагая серверу перейти на протокол WebSocket.
- Если сервер поддерживает WebSockets, соединение «апгрейдится» и открывается двунаправленный канал.
- Теперь клиент и сервер могут обмениваться сообщениями в реальном времени, без дополнительных запросов.
В отличие от polling (регулярного опроса сервера) или long-polling (длинных висящих запросов), WebSocket-соединение:
- экономит трафик (нет постоянных HTTP-заголовков),
- снижает задержку доставки,
- может работать в обе стороны: и сервер, и клиент могут первыми инициировать отправку.
// Установка соединения
const socket = new WebSocket("ws://localhost:3000");
// Событие открытия соединения
socket.addEventListener("open", () => {
console.log("Соединение установлено");
socket.send("Привет, сервер!");
});
// Получение сообщений от сервера
socket.addEventListener("message", (event) => {
console.log("Сообщение от сервера:", event.data);
});
// Обработка закрытия
socket.addEventListener("close", () => {
console.log("Соединение закрыто");
});
Использование на бэкенде (пример на Node.js с ws)
Установим библиотеку:
npm install ws
Простейший сервер:
import { WebSocketServer } from "ws";
const wss = new WebSocketServer({ port: 3000 });
wss.on("connection", (ws) => {
console.log("Новый клиент подключен");
ws.on("message", (message) => {
console.log("Получено:", message.toString());
ws.send(`Эхо: ${message}`);
});
ws.on("close", () => {
console.log("Клиент отключился");
});
});
Теперь клиенты могут подключаться и обмениваться сообщениями в реальном времени.
Безопасность при работе с WebSockets
Так как WebSocket-соединение остаётся открытым длительное время, важно заранее подумать о безопасности. Вот три основных практики:
Аутентификация соединений
Используйте JWT-токены или другие методы проверки пользователя.
Пример: клиент подключается к ws://localhost:8080?token=JWT_HERE
, а сервер валидирует токен при апгрейде соединения.
import http from "http";
import WebSocket, { WebSocketServer } from "ws";
import jwt from "jsonwebtoken";
const server = http.createServer();
const wss = new WebSocketServer({ noServer: true });
// апгрейд соединения с аутентификацией
server.on("upgrade", (req, socket, head) => {
try {
const url = new URL(req.url, `http://${req.headers.host}`);
const token = url.searchParams.get("token");
if (!token) throw new Error("No token provided");
// верификация JWT-токена
jwt.verify(token, "your-secret-key", (err, decoded) => {
if (err) {
socket.write("HTTP/1.1 401 Unauthorized\r\n\r\n");
socket.destroy();
return;
}
// посылаем WebSocket-хэндшейк
wss.handleUpgrade(req, socket, head, (ws) => {
ws.user = decoded;
wss.emit("connection", ws, req);
});
});
} catch {
socket.write("HTTP/1.1 401 Unauthorized\r\n\r\n");
socket.destroy();
}
});
wss.on("connection", (ws) => {
ws.send("Добро пожаловать! Аутентификация прошла успешно ✅");
});
server.listen(8080);
В примере создаётся обычный HTTP-сервер:
const server = http.createServer();
const wss = new WebSocketServer({ noServer: true });
Почему так?
- HTTP-сервер слушает порт и принимает все входящие соединения.
- Параметр
noServer: true
говорит, что WebSocket-сервер сам порт не открывает. - Вместо этого мы вручную перехватываем запросы на апгрейд (
server.on('upgrade')
), проверяем токен и только потом передаём соединение вwss.handleUpgrade(...)
.
Такой подход позволяет объединить обычные HTTP-запросы и WebSocket-подключения на одном порту и встроить аутентификацию прямо в процесс апгрейда.
Rate limiting (ограничение частоты сообщений)
Чтобы избежать спама и DoS-атак, ограничивайте количество сообщений от клиента.
import rateLimit from "ws-rate-limit";
const limiter = rateLimit({
windowMs: 60 * 1000, // 1 минута
max: 100, // не более 100 сообщений
message: "Слишком много сообщений, замедлитесь!",
});
wss.on("connection", (ws) => {
limiter(ws);
ws.on("message", (msg) => {
console.log("Получено:", msg.toString());
});
});
Где применять WebSockets
- Чаты и мессенджеры
- Онлайн-игры
- Финансовые системы (котировки, биржевые данные)
- Совместное редактирование документов
- Live-уведомления (например, новые комментарии или лайки)
Альтернативы
В ряде случаев вместо WebSockets можно использовать Server-Sent Events (SSE) или WebRTC (для P2P-связи). Но WebSockets — наиболее универсальное решение для большинства задач real-time.
Итог
WebSocket — это современный способ устанавливать постоянное соединение между браузером и сервером.
- У WebSocket нет ограничений по кросс-доменным запросам.
- Поддержка во всех популярных браузерах.
- Можно передавать как строки, так и бинарные данные.
- API очень простой.
Методы:
socket.send(data)
socket.close([code], [reason])
События:
open
message
error
close
Однако сам по себе WebSocket не включает механизмы повторного подключения, аутентификации и другие высокоуровневые возможности. Для этого существуют клиентские/серверные библиотеки, но также можно реализовать всё вручную.
Настроить мониторинг за 30 секунд
Надежные оповещения о даунтаймах. Без ложных срабатываний