WebSocket на JavaScript: real-time приложения от А до Я

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение в WebSocket на JavaScript: что такое real-time связь?

В современном вебе пользователи привыкли к мгновенным обновлениям: сообщения в чатах приходят без перезагрузки страницы, котировки акций меняются в реальном времени, а в онлайн-играх действия соперников видны сразу. Всё это стало возможным благодаря технологии WebSocket — протоколу, который обеспечивает постоянное двустороннее соединение между клиентом и сервером.

В отличие от классического HTTP-запроса, где клиент отправляет запрос и ждёт ответ, WebSocket позволяет серверу самостоятельно отправлять данные клиенту в любой момент. Это открывает безграничные возможности для создания real-time приложений на JavaScript. В этой статье мы разберём WebSocket от основ до создания полноценного чата на Node.js.

Основы WebSocket: как работает протокол

Что такое WebSocket и чем он отличается от HTTP?

WebSocket — это протокол связи, работающий поверх TCP. Он начинается как HTTP-запрос (рукопожатие), после чего соединение "апгрейдится" до WebSocket, и данные передаются в обоих направлениях без дополнительных заголовков. Это делает его идеальным для приложений, где важна низкая задержка.

Основные преимущества WebSocket перед традиционными методами (Polling, Long Polling):

  • Постоянное соединение — не нужно создавать новый HTTP-запрос для каждого обновления
  • Низкая задержка — данные передаются мгновенно, как только появляются на сервере
  • Экономия трафика — минимальный размер фреймов (всего 2 байта служебных данных)
  • Двусторонняя связь — сервер может инициировать отправку данных

Установка соединения: рукопожатие

Процесс начинается с HTTP-запроса от клиента, содержащего заголовок Upgrade: websocket. Сервер, поддерживающий WebSocket, отвечает статусом 101 Switching Protocols. После этого соединение считается установленным.

// Пример HTTP-запроса на установку WebSocket
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

Создание WebSocket сервера на Node.js

Установка и настройка ws-библиотеки

Для работы с WebSocket на серверной стороне мы будем использовать популярную библиотеку ws. Она легковесна, быстра и полностью соответствует спецификации протокола.

// Установка библиотеки
// npm install ws

Создадим простой WebSocket-сервер:

const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', (ws) => {
    console.log('Новый клиент подключился');
    
    ws.on('message', (message) => {
        console.log('Получено сообщение:', message.toString());
        // Отправляем ответ всем подключённым клиентам
        wss.clients.forEach((client) => {
            if (client.readyState === WebSocket.OPEN) {
                client.send(`Эхо: ${message}`);
            }
        });
    });
    
    ws.send('Добро пожаловать на WebSocket сервер!');
});

console.log('WebSocket сервер запущен на порту 8080');

Подключение клиента на JavaScript

На стороне клиента (браузер) используется встроенный объект WebSocket:

const socket = new WebSocket('ws://localhost:8080');

socket.onopen = () => {
    console.log('Соединение установлено');
    socket.send('Привет, сервер!');
};

socket.onmessage = (event) => {
    console.log('Сообщение от сервера:', event.data);
};

socket.onclose = () => {
    console.log('Соединение закрыто');
};

socket.onerror = (error) => {
    console.error('Ошибка WebSocket:', error);
};

Создание real-time чата на JavaScript и Node.js

Архитектура приложения

Мы построим полноценный чат с поддержкой множества пользователей. Каждое сообщение будет транслироваться всем подключённым клиентам. Для идентификации пользователей добавим простую систему имён.

Серверная часть чата

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 3000 });

const clients = new Map(); // Храним id клиента и его имя

wss.on('connection', (ws) => {
    const clientId = Date.now();
    clients.set(ws, { id: clientId, name: `User_${clientId}` });
    
    // Уведомляем всех о новом пользователе
    broadcast({ type: 'system', message: `${clients.get(ws).name} присоединился к чату` }, ws);
    
    ws.on('message', (data) => {
        const parsed = JSON.parse(data);
        if (parsed.type === 'setName') {
            clients.get(ws).name = parsed.name;
            broadcast({ type: 'system', message: `Пользователь сменил имя на ${parsed.name}` });
        } else if (parsed.type === 'message') {
            const sender = clients.get(ws).name;
            broadcast({ type: 'message', sender, text: parsed.text, time: new Date().toLocaleTimeString() });
        }
    });
    
    ws.on('close', () => {
        const user = clients.get(ws);
        broadcast({ type: 'system', message: `${user.name} покинул чат` });
        clients.delete(ws);
    });
});

function broadcast(data, excludeWs = null) {
    wss.clients.forEach((client) => {
        if (client !== excludeWs && client.readyState === WebSocket.OPEN) {
            client.send(JSON.stringify(data));
        }
    });
}

console.log('Чат-сервер запущен на ws://localhost:3000');

Клиентская часть чата (HTML + JavaScript)

<!DOCTYPE html>
<html>
<head>
    <title>Real-time Чат</title>
</head>
<body>
    <div id="messages"></div>
    <input type="text" id="nameInput" placeholder="Ваше имя" />
    <input type="text" id="msgInput" placeholder="Сообщение" />
    <button onclick="sendMessage()">Отправить</button>
    
    <script>
        const socket = new WebSocket('ws://localhost:3000');
        const messagesDiv = document.getElementById('messages');
        
        socket.onmessage = (event) => {
            const data = JSON.parse(event.data);
            const msgElement                

Блоги

Рекомендаций по книгам