Socket.IO: создание real-time приложений на Node.js
Saad Takhir · · 0 просмотров

Проблема: HTTP «не умеет говорить первым»
В обычном HTTP общение одностороннее: браузер спрашивает, сервер отвечает. Сервер не может сам сообщить «пришло новое сообщение».
А для чатов, живых уведомлений, онлайн-игр или отображения статуса заказа в реальном времени нужно именно это. Постоянно опрашивать сервер каждую секунду («есть что-нибудь новое?», т.е. polling) — это лишняя нагрузка и задержки.
Что такое Socket.IO?
Socket.IO — библиотека для двусторонней real-time связи между сервером и клиентом (браузером, мобильным приложением). В основе у неё WebSocket, но она даёт гораздо больше:
- Автоматическое переподключение — если интернет пропал, клиент сам подключится заново.
- Резервный транспорт — если WebSocket недоступен, переходит на HTTP long-polling.
- События (events) — данные передаются через именованные события.
- Комнаты (rooms) — разделение пользователей на группы.
- Подтверждения (acknowledgements) — можно узнать, что сообщение дошло.
⚠️ Socket.IO — это не «чистый» WebSocket. Обычный WebSocket-клиент не сможет подключиться к серверу Socket.IO — Socket.IO нужен с обеих сторон.
Установка
npm install socket.io # для сервера
npm install socket.io-client # для фронтенда
Сервер
import { createServer } from 'node:http'
import { Server } from 'socket.io'
const httpServer = createServer()
const io = new Server(httpServer, {
cors: { origin: 'http://localhost:5173' }
})
io.on('connection', (socket) => {
console.log('Новое подключение:', socket.id)
socket.on('chat:message', (text) => {
// Всем, включая отправителя
io.emit('chat:message', { id: socket.id, text })
})
socket.on('disconnect', () => {
console.log('Отключился:', socket.id)
})
})
httpServer.listen(3000, () => {
console.log('Socket-сервер: http://localhost:3000')
})
Клиент (фронтенд)
import { io } from 'socket.io-client'
const socket = io('http://localhost:3000')
socket.on('connect', () => {
console.log('Подключились!', socket.id)
})
socket.on('chat:message', (msg) => {
console.log(`${msg.id}: ${msg.text}`)
})
socket.emit('chat:message', 'Всем привет!')
Главная идея проста: emit — отправить событие, on — слушать событие. На обеих сторонах это работает одинаково.
Кому отправлять?
socket.emit('event', data) // только этому пользователю
io.emit('event', data) // всем
socket.broadcast.emit('event', data) // всем, кроме отправителя
io.to('room-1').emit('event', data) // только участникам комнаты
Комнаты (rooms)
Например, отдельная комната для каждого чата или каждого заказа:
socket.on('room:join', (roomId) => {
socket.join(roomId)
socket.to(roomId).emit('room:notice', `${socket.id} присоединился`)
})
Комнаты существуют только на сервере — клиент их не видит, он просто получает сообщения.
Подтверждение (acknowledgement)
Чтобы узнать, что сообщение дошло до сервера и было обработано:
// Клиент
const res = await socket.emitWithAck('order:create', { item: 'Pizza' })
console.log(res.status) // 'ok'
// Сервер
socket.on('order:create', (order, callback) => {
// ... сохранение в базу
callback({ status: 'ok' })
})
Где используется?
- Чаты и мессенджеры
- Статус заказа (кафе, доставка)
- Живые уведомления
- Real-time статистика в админ-панели
- Онлайн-игры и совместное редактирование
Важные советы
- Аутентификация — проверяйте токен при подключении:
io(url, { auth: { token } })и middlewareio.use()на сервере. - Имена событий — имена с префиксами вроде
chat:message,order:updateпомогают держать код в порядке. - Несколько серверов — когда проект вырастет до нескольких серверов, понадобится Redis adapter, иначе серверы не будут видеть клиентов друг друга.
- Валидация данных — не доверяйте данным от клиента, проверяйте их так же, как в REST API.
Итог
Socket.IO сильно упрощает добавление real-time функций: несколькими строками кода вы получаете рабочий чат или систему живых уведомлений. Начните с небольшого чат-приложения — это лучший способ разобраться в Socket.IO.