WebSocket на JavaScript: создаём real-time приложения с Node.js
Современные веб-приложения требуют мгновенного обмена данными между клиентом и сервером. Традиционный HTTP-протокол, основанный на запросах-ответах, плохо подходит для задач, где важна скорость: онлайн-чаты, биржевые котировки, многопользовательские игры или системы уведомлений. Именно здесь на помощь приходит протокол WebSocket. В этой статье мы разберём, как работает WebSocket на JavaScript, и создадим простое real-time приложение на Node.js.
Что такое WebSocket и зачем он нужен?
WebSocket — это протокол полнодуплексной связи (full-duplex) поверх TCP-соединения. В отличие от HTTP, где клиент всегда инициирует запрос, WebSocket позволяет серверу самостоятельно отправлять данные клиенту в любой момент. Это достигается за счёт установки постоянного двустороннего канала после первоначального handshake.
Основные преимущества WebSocket перед HTTP:
- Низкая задержка — данные передаются мгновенно без повторных HTTP-заголовков.
- Экономия трафика — минимальный служебный оверхед после установки соединения.
- Постоянное соединение — нет необходимости в polling или long-polling.
- Двусторонняя связь — сервер может инициировать отправку данных.
WebSocket идеально подходит для real-time приложений: чаты, уведомления, совместное редактирование документов, финансовые терминалы и онлайн-игры.
Установка и настройка WebSocket сервера на Node.js
Для работы с WebSocket на Node.js мы будем использовать популярную библиотеку ws. Она легковесна, надёжна и хорошо документирована.
Начнём с установки:
npm init -y
npm install ws
Теперь создадим простой сервер WebSocket, который будет принимать соединения и отвечать на сообщения:
// server.js
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', function connection(ws) {
console.log('Клиент подключился');
// Отправляем приветственное сообщение
ws.send('Добро пожаловать на WebSocket сервер!');
// Обрабатываем входящие сообщения
ws.on('message', function incoming(message) {
console.log('Получено: %s', message);
// Отправляем ответ всем подключенным клиентам
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
client.send(`Эхо: ${message}`);
}
});
});
// Обрабатываем закрытие соединения
ws.on('close', function close() {
console.log('Клиент отключился');
});
});
console.log('WebSocket сервер запущен на ws://localhost:8080');
Запустите сервер командой node server.js. Сервер готов принимать подключения.
Создание клиентской части на JavaScript
Клиентская часть работает прямо в браузере. WebSocket API встроен во все современные браузеры, поэтому никаких дополнительных библиотек не требуется.
Создадим HTML-страницу с простым интерфейсом:
<!DOCTYPE html>
<html>
<head>
<title>WebSocket Чат</title>
<style>
#messages { height: 300px; overflow-y: scroll; border: 1px solid #ccc; padding: 10px; margin-bottom: 10px; }
#input { width: 300px; }
</style>
</head>
<body>
<h2>Real-time Чат</h2>
<div id="messages"></div>
<input type="text" id="input" placeholder="Введите сообщение..." />
<button onclick="sendMessage()">Отправить</button>
<script>
// Подключаемся к WebSocket серверу
const socket = new WebSocket('ws://localhost:8080');
// Обработчик открытия соединения
socket.addEventListener('open', function (event) {
addMessage('Соединение установлено');
});
// Обработчик получения сообщения
socket.addEventListener('message', function (event) {
addMessage('Сервер: ' + event.data);
});
// Обработчик ошибок
socket.addEventListener('error', function (event) {
addMessage('Ошибка: ' + event.message);
});
// Обработчик закрытия соединения
socket.addEventListener('close', function (event) {
addMessage('Соединение закрыто');
});
function sendMessage() {
const input = document.getElementById('input');
const message = input.value;
if (message) {
socket.send(message);
addMessage('Вы: ' + message);
input.value = '';
}
}
function addMessage(text) {
const messages = document.getElementById('messages');
const p = document.createElement('p');
p.textContent = text;
messages.appendChild(p);
messages.scrollTop = messages.scrollHeight;
}
</script>
</body>
</html>
Откройте эту HTML-страницу в браузере. Вы увидите, что сообщения мгновенно отправляются на сервер и возвращаются обратно всем подключенным клиентам.
Расширенный пример: комнаты и broadcast
В реальных приложениях часто требуется разделять пользователей по комнатам (например, чаты). Давайте реализуем эту логику на сервере.
// advanced-server.js
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
const rooms = new Map(); // roomName -> Set of WebSocket connections
wss.on('connection', function connection(ws) {
let currentRoom = null;
ws.on('message', function incoming(message) {
const data = JSON.parse(message);
switch (data.type) {
case 'join':
// Покидаем предыдущую комнату
if (currentRoom && rooms.has(currentRoom)) {
rooms.get(currentRoom).delete(ws);
if (rooms.get(currentRoom).size === 0) {
rooms.delete(currentRoom);
}
}
// Входим в новую комнату
currentRoom = data.room;
if (!rooms.has(currentRoom)) {
rooms.set(currentRoom, new Set());
}
rooms.get(currentRoom).add(ws);
ws.send(JSON.stringify({ type: 'system', message: `Вы вошли в комнату ${currentRoom}` }));
broadcast(currentRoom, { type: 'system', message: 'Новый пользователь присоединился' }, ws);
break;
case 'message':
if (currentRoom) {
broadcast(currentRoom, { type: 'message', user: data.user, text: data.text }, ws);
}
break;
case 'leave':
if (currentRoom && rooms.has(currentRoom)) {
rooms.get(currentRoom).delete(ws);
broadcast(currentRoom, {