Все посты

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 } }) и middleware io.use() на сервере.
  • Имена событий — имена с префиксами вроде chat:message, order:update помогают держать код в порядке.
  • Несколько серверов — когда проект вырастет до нескольких серверов, понадобится Redis adapter, иначе серверы не будут видеть клиентов друг друга.
  • Валидация данных — не доверяйте данным от клиента, проверяйте их так же, как в REST API.

Итог

Socket.IO сильно упрощает добавление real-time функций: несколькими строками кода вы получаете рабочий чат или систему живых уведомлений. Начните с небольшого чат-приложения — это лучший способ разобраться в Socket.IO.

Поделиться · 0 репостов
Связаться