Что такое Socket.io и зачем он нужен?
Socket.io — это мощная JavaScript-библиотека, которая обеспечивает real-time (реальное время) двунаправленную коммуникацию между клиентом (браузером) и сервером (Node.js). В отличие от традиционного HTTP-протокола, где клиент отправляет запрос и ждет ответа, Socket.io позволяет серверу самостоятельно инициировать отправку данных клиенту в любой момент, и наоборот.
Зачем это нужно? Представьте себе чат-приложение, онлайн-игру, панель мониторинга с живыми графиками или систему совместного редактирования документов. Во всех этих сценариях данные должны обновляться мгновенно, без перезагрузки страницы. HTTP для этого не подходит, так как он работает по принципу "запрос-ответ". Socket.io решает эту проблему, устанавливая постоянное соединение (обычно через WebSocket), по которому данные могут передаваться в обе стороны в любой момент.
Ключевые особенности Socket.io:
- Двунаправленность: Сервер и клиент могут отправлять сообщения друг другу.
- Real-time: Сообщения доставляются мгновенно (с минимальной задержкой).
- Автоматическое переподключение: Если соединение обрывается, Socket.io сам пытается его восстановить.
- Комнаты (Rooms): Возможность группировать клиентов и отправлять сообщения только определенной группе.
- Пространства имен (Namespaces): Разделение приложения на независимые каналы связи.
- Надежность: Если WebSocket не поддерживается, Socket.io автоматически переключается на другие методы (long-polling, FlashSocket и т.д.).
Установка Socket.io
Socket.io состоит из двух частей: серверной (для Node.js) и клиентской (для браузера). Обе устанавливаются через npm.
Установка серверной части
Откройте терминал в папке вашего проекта и выполните команду:
npm install socket.io
Установка клиентской части
Клиентский скрипт можно подключить двумя способами:
1. Через CDN (проще всего для начала):
<script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script>
2. Через npm (для проектов со сборщиками, например, Webpack):
npm install socket.io-client
Быстрый старт: первый чат
Давайте создадим простейший чат, где сообщения от одного клиента видят все остальные.
Шаг 1: Сервер (файл server.js)
// server.js
const http = require('http');
const { Server } = require("socket.io");
// 1. Создаем HTTP сервер
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Socket.io сервер запущен');
});
// 2. Создаем экземпляр Socket.io, привязанный к серверу
const io = new Server(server);
// 3. Обработчик подключения нового клиента
io.on('connection', (socket) => {
console.log('Новый пользователь подключился:', socket.id);
// 4. Слушаем событие 'chat message' от клиента
socket.on('chat message', (msg) => {
console.log('Сообщение:', msg);
// 5. Отправляем сообщение ВСЕМ подключенным клиентам (включая отправителя)
io.emit('chat message', msg);
});
// 6. Обработчик отключения клиента
socket.on('disconnect', () => {
console.log('Пользователь отключился:', socket.id);
});
});
// 7. Запускаем сервер на порту 3000
server.listen(3000, () => {
console.log('Сервер запущен на http://localhost:3000');
});
Шаг 2: Клиент (файл index.html)
<!DOCTYPE html>
<html>
<head>
<title>Socket.io чат</title>
<script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script>
</head>
<body>
<ul id="messages"></ul>
<form id="form" action="">
<input id="input" autocomplete="off" /><button>Отправить</button>
</form>
<script>
// 1. Подключаемся к серверу
const socket = io('http://localhost:3000');
// 2. Получаем элементы DOM
const form = document.getElementById('form');
const input = document.getElementById('input');
const messages = document.getElementById('messages');
// 3. Обработчик отправки формы
form.addEventListener('submit', (e) => {
e.preventDefault();
if (input.value) {
// 4. Отправляем сообщение на сервер
socket.emit('chat message', input.value);
input.value = '';
}
});
// 5. Слушаем событие 'chat message' от сервера
socket.on('chat message', (msg) => {
const item = document.createElement('li');
item.textContent = msg;
messages.appendChild(item);
window.scrollTo(0, document.body.scrollHeight);
});
</script>
</body>
</html>
Шаг 3: Запуск
Запустите сервер командой:
node server.js
Откройте index.html в двух разных вкладках браузера. Теперь сообщения, отправленные в одной вкладке, будут мгновенно появляться в другой.
Основные методы и функции Socket.io
Рассмотрим ключевые методы, которые используются в 90% проектов. Методы разделены на серверные и клиентские.
Серверные методы (используются в server.js)
1. io.on('connection', callback)
Что делает: Это главное событие на сервере. Оно срабатывает каждый раз, когда новый клиент успешно подключается к серверу. Внутри колбэка вы получаете объект socket, который представляет подключение конкретного клиента.
Параметры:
'connection'— строка, имя события (обязательно).callback(socket)— функция, которая выполняется при подключении. Принимает объектsocket.
Пример:
io.on('connection', (socket) => {
console.log('Клиент подключился:', socket.id);
// Здесь можно навешивать обработчики для этого конкретного клиента
socket.on('some event', (data) => { /* ... */ });
});
2. io.emit(eventName, data)
Что делает: Отправляет сообщение (событие) всем подключенным клиентам одновременно. Это "глобальная рассылка".
Параметры:
eventName(String) — имя события, которое будут слушать клиенты.data(Any) — данные, которые передаются вместе с событием. Может быть строкой, числом, объектом, массивом и т.д.
Пример:
// Сервер отправляет всем клиентам текущее время каждую секунду
setInterval(() => {
const time = new Date().toLocaleTimeString();
io.emit('server time', time);
}, 1000);
3. socket.emit(eventName, data)
Что делает: Отправляет сообщение только одному конкретному клиенту, который представлен этим объектом socket. Остальные клиенты это сообщение не получат.
Параметры:
eventName(String) — имя события.data(Any) — данные.
Пример:
// Отправляем приветствие только что подключившемуся клиенту
io.on('connection', (socket) => {
socket.emit('welcome', 'Добро пожаловать в чат!');
});
4. socket.broadcast.emit(eventName, data)
Что делает: Отправляет сообщение всем клиентам, кроме отправителя. Очень полезно для чатов, чтобы не дублировать сообщение тому, кто его отправил.
Параметры:
eventName(String) — имя события.data(Any) — данные.
Пример:
socket.on('chat message', (msg) => {
// Отправляем всем, кроме отправителя
socket.broadcast.emit('chat message', msg);
});
5. socket.join(roomName)
Что делает: Позволяет клиенту "войти" в определенную комнату. Комнаты — это логические группы, которым можно отправлять сообщения, не затрагивая остальных. Например, можно создать комнаты для разных игровых сессий или чатов.
Параметры:
roomName(String) — название комнаты.
Пример:
socket.on('join room', (room) => {
socket.join(room);
console.log(`Клиент ${socket.id} присоединился к комнате ${room}`);
// Отправляем сообщение только участникам этой комнаты
io.to(room).emit('room message', `Новый участник в комнате ${room}`);
});
6. io.to(roomName).emit(eventName, data)
Что делает: Отправляет сообщение всем клиентам, которые находятся в указанной комнате. Это основная функция для работы с комнатами.
Параметры:
roomName(String) — название комнаты.eventName(String) — имя события.data(Any) — данные.
Пример:
// Отправляем сообщение всем в комнате 'game-123'
io.to('game-123').emit('game update', { score: 10, player: 'Alice' });
7. socket.on(eventName, callback)
Что делает: Подписывается на входящее событие от конкретного клиента. Это основной способ получения данных от клиента на сервере.
Параметры:
eventName(String) — имя события, которое отправляет клиент.callback(data)— функция, которая выполняется при получении события. Принимает данные, отправленные клиентом.
Пример:
socket.on('user message', (messageData) => {
console.log(`Получено сообщение от ${messageData.user}: ${messageData.text}`);
});
8. socket.disconnect(close)
Что делает: Принудительно отключает клиента от сервера. Вызывается со стороны сервера.
Параметры:
close(Boolean, опционально) — еслиtrue, закрывает транспортное соединение (например, WebSocket). По умолчаниюfalse.
Пример:
// Отключаем клиента, если он нарушил правила
socket.on('bad behavior', () => {
socket.disconnect(true);
});
Клиентские
Также в библиотеке
Геолокация и карты в C# (.NET): обзор библиотек и инструментов
Генерация PDF отчётов на C# (.NET) с iTextSharp и QuestPDF
Rate Limiting в Go (Golang): библиотеки, паттерны и примеры реализации
PHP-DI для PHP: полное руководство с примерами