Socket.io: обзор
Socket.io — библиотека для двусторонней коммуникации в реальном времени, надстраивающая WebSocket с автоматическим fallback, комнатами и событийной моделью.
Зачем нужно
Нативный WebSocket требует ручного управления переподключением, нет встроенных комнат и namespace. Socket.io добавляет: автоматическое переподключение, fallback на long polling при недоступности WS, именованные события, комнаты для групповой рассылки и поддержку нескольких транспортов. Идеален для чатов, коллаборативных инструментов и многопользовательских игр.
Где используется
- Чаты и мессенджеры (комнаты, группы)
- Совместное редактирование (Google Docs-подобные функции)
- Игры в реальном времени (синхронизация состояния)
- Live-дэшборды и мониторинг
Сервер (Node.js)
// npm install socket.io
const { createServer } = require('http');
const { Server } = require('socket.io');
const express = require('express');
const app = express;
const httpServer = createServer(app);
const io = new Server(httpServer, {
cors: { origin: 'http://localhost:3000', methods: ['GET', 'POST'] },
});
io.on('connection', (socket) => {
console.log('Подключён:', socket.id);
// Слушаем событие от клиента
socket.on('chat:message', ({ room, text, user }) => {
// Рассылаем всем в комнате, включая отправителя
io.to(room).emit('chat:message', { text, user, timestamp: Date.now() });
});
// Вход в комнату
socket.on('room:join', (roomId) => {
socket.join(roomId);
socket.to(roomId).emit('room:user-joined', { userId: socket.id });
});
// Выход из комнаты
socket.on('room:leave', (roomId) => {
socket.leave(roomId);
socket.to(roomId).emit('room:user-left', { userId: socket.id });
});
socket.on('disconnect', () => {
console.log('Отключён:', socket.id);
});
});
httpServer.listen(4000);
Клиент (браузер)
// npm install socket.io-client
import { io } from 'socket.io-client';
const socket = io('http://localhost:4000', {
auth: { token: localStorage.getItem('token') },
reconnection: true,
reconnectionDelay: 1000,
reconnectionAttempts: 5,
});
// Отправка события
socket.emit('room:join', 'general');
socket.emit('chat:message', {
room: 'general',
text: 'Привет!',
user: 'Антон',
});
// Приём событий
socket.on('chat:message', ({ text, user, timestamp }) => {
addMessageToUI({ text, user, timestamp });
});
socket.on('room:user-joined', ({ userId }) => {
showNotification(`${userId} вошёл в комнату`);
});
// Управление подключением
socket.on('connect', () => console.log('Подключён:', socket.id));
socket.on('disconnect', reason => console.log('Отключён:', reason));
socket.on('connect_error', err => console.error('Ошибка:', err.message));
// Закрыть соединение
function cleanup() { socket.disconnect(); }
Комнаты и Namespace
// Сервер: namespace — логическая группа соединений
const adminNs = io.of('/admin');
adminNs.on('connection', socket => { /* только для /admin */ });
// Клиент: подключение к namespace
const adminSocket = io('http://localhost:4000/admin');
// Rooms — подмножества соединений в namespace
// broadcast в комнату (кроме отправителя)
socket.to('room-id').emit('event', data);
// broadcast всем в комнате (включая отправителя)
io.to('room-id').emit('event', data);
Частые ошибки
- Забывают настроить CORS — соединение отклоняется браузером
- Используют Socket.io там, где достаточно SSE — однонаправленный поток не требует WebSocket
- Не обрабатывают
disconnect— утечка подписчиков и состояния комнат - Хранят состояние в памяти процесса при горизонтальном масштабировании — нужен Redis adapter