Skip to content

Перевод документации и API socket.io на русский язык

License

Notifications You must be signed in to change notification settings

DASenkiv/Socket.IO-RU

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 

Repository files navigation

Документация библиотеки Socket.IO на русском языке

[ENG]:This is russian translation of official documentation socket.io (https://socket.io/docs/).

[RU]: Перевод документации socket.io на русский язык (https://socket.io/docs/).

Актуальность: май 2019

От переводчика:

не смог найти достаточно подробный обзор, сайт с описанием данной библиотеки, кроме англоязычной документации socket.io, а на хабраютубах не находил ничего сложнее чата на вебсокетах. Поэтому принял решение перевести официальную документацию на великий и могучий :)

Также перевод будет дополнен ответами на часто задаваемые вопросы и примерами.

Пожелания, замечания пишите в twitter или в issue на гитхабе. Лучшей помощью, не считая доната, является помощь с переводом и распространение данной информации. Ну и, конечно, звезда на репозитории.

P. S. здесь и далее будет удалена точка из названий библиотек, поскольку точка генерирует ссылку и вводит читателей в заблуждение (например, вместо Engine.IO будет написано EngineIO, вместо Socket.IO - SocketIO и т. д. В тех местах, где ссылка присутствует, она является верной.

Содержание

Обзор

SocketIO - это библиотека, которая обеспечивает двустороннюю и основанную на событиях связь в режиме реального времени между браузером и сервером. Она состоит из:

Его основными особенностями являются:

Надежность

Соединения устанавливаются даже при наличии:

  • прокси-серверов и балансировщиков нагрузки;
  • персональных брандмауэров и антивирусного ПО. Для этой цели используется EngineIO, который сначала устанавливает long-polling соединение, а затем пытается улучшить его до WebSocket.

Поддержка автоматического переподключения

Если не указано иное, отключенный клиент будет пытаться восстановить соединение до тех пор, пока сервер снова не станет доступен.

Обнаружение разъединения

Механизм heartbeat (вики: «сердцебиение» — это периодический сигнал, генерируемый аппаратным или программным обеспечением для индикации нормальной работы или для синхронизации других частей компьютерной системы) реализован на уровне EngineIO, что позволяет как серверу, так и клиенту знать, когда собеседник больше не отвечает.

Эта функциональность достигается с помощью таймеров, установленных как на сервере, так и на клиенте, со значениями тайм-аута (параметры pingInterval и pingTimeout), которые используются совместно при установлении соединения. Эти таймеры требуют, чтобы любые последующие клиентские вызовы направлялись на один и тот же сервер, поэтому при использовании нескольких узлов (нод) требуется механизм sticky session.

Sticky session — метод балансировки нагрузки, при котором запросы клиента передаются на один и тот же сервер группы.

Поддержка бинарных типов данных

Любые сериализуемые структуры данных могут быть переданы, в том числе:

Сериализация — процесс перевода какой-либо структуры данных в последовательность битов.

Поддержка мультиплексирования

Чтобы создать разделение групп в вашем приложении (например, для каждого модуля или на основе разрешений), SocketIO позволяет вам создать несколько пространств имен, которые будут действовать как отдельные каналы связи, но будут использовать одно и то же базовое соединение.

Поддержка комнат (room)

В каждом пространстве имен вы можете определить произвольные каналы, называемые комнатами, к которым сокеты могут присоединяться и отсоединяться. Затем вы можете транслировать в любую комнату, достигнув каждого сокета, который присоединился к ней.

Это полезная функция для отправки уведомлений группе пользователей или данному пользователю, например, подключенному к нескольким устройствам. Эти функции поставляются с простым и удобным API, который выглядит следующим образом:

io.on('connection', function(socket){
  socket.emit('request', /* */); // отправить событие в сокет
  io.emit('broadcast', /* */); // отправить событие на все подключенные сокеты
  socket.on('reply', function(){ /* */ }); // слушать событие
});

Чем SocketIO не является

SocketIO НЕ является реализацией WebSocket. Хотя SocketIO действительно использует WebSocket в качестве протокола передачи данных, когда это возможно, он добавляет некоторые метаданные к каждому пакету: тип пакета, пространство имен и идентификатор ACK, когда требуется подтверждение сообщения. Вот почему клиент WebSocket не сможет успешно подключиться к серверу SocketIO, а клиент SocketIO также не сможет подключиться к серверу WebSocket.

// ВНИМАНИЕ: клиент НЕ сможет подключиться!
const client = io ('ws: //echo.websocket.org');

Установка

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

npm install --save socket.io

Исходный код

Javascript клиент

Автономная сборка клиента предоставляется по умолчанию сервером по адресу /socket.io/socket.io.js.

Также это может быть сделано из CDN, через cdnjs.

Для использования c Node.js, или с помощью сборщика, например, webpack или browserify, вы также можете установить пакетную сборку из npm:

npm install --save socket.io-client

Исходный код

Реализации клиента на других языках программирования

Существует несколько реализаций клиента на других языках, которые поддерживаются сообществом:

Использование с http-сервером Node

Сервер (app.js)

var app = require('http').createServer(handler)
var io = require('socket.io')(app);
var fs = require('fs');

app.listen(80);

function handler (req, res) {
  fs.readFile(__dirname + '/index.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading index.html');
    }

    res.writeHead(200);
    res.end(data);
  });
}

io.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});

Клиент (index.html)

<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io('http://localhost');
  socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });
</script>

Использование с Express

Сервер (app.js)

var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);

server.listen(80);
// ВНИМАНИЕ: app.listen(80) здесь не будет работать!

app.get('/', function (req, res) {
  res.sendFile(__dirname + '/index.html');
});

io.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});

Клиент (index.html)

<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost');
  socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });
</script>

Отправка и получение событий

Socket.IO позволяет отправлять и получать пользовательские события. Кроме connect, message и disconnect, вы можете создавать свои события:

Сервер

// note, io(<port>) создаст http сервер
var io = require('socket.io')(80);

io.on('connection', function (socket) {
  io.emit('this', { will: 'будет принято всеми'});

  socket.on('private message', function (from, msg) {
    console.log('Я получил личное сообщение от ', from, ' который сказал ', msg);
  });

  socket.on('disconnect', function () {
    io.emit('Пользователь отсоединился');
  });
});

Ограничение пространством имен

Если у вас есть контроль над всеми сообщениями и событиями, генерируемыми и отправляемыми для конкретного приложения, работает пространство имен по умолчанию. Если вы хотите использовать сторонний код или создавать код для совместного использования с другими, socket.io предоставляет способ создания пространства имен для сокета.

Это дает возможность мультиплексировать одно соединение. Вместо использования двух соединений типа WebSocket, SocketIO использует одно.

Сервер (app.js)

var io = require('socket.io')(80);
var chat = io
  .of('/chat')
  .on('connection', function (socket) {
    socket.emit('a message', {
        that: 'only'
      , '/chat': 'will get'
    });
    chat.emit('a message', {
        everyone: 'in'
      , '/chat': 'will get'
    });
  });

var news = io
  .of('/news')
  .on('connection', function (socket) {
    socket.emit('item', { news: 'item' });
  });

Клиент (index.html)

<script>
  var chat = io.connect('http://localhost/chat')
    , news = io.connect('http://localhost/news');
  
  chat.on('connect', function () {
    chat.emit('hi!');
  });
  
  news.on('news', function () {
    news.emit('woot');
  });
</script>

Отправка нестабильных сообщений

Иногда определенные сообщения могут быть сброшены. Допустим, у вас есть приложение, которое показывает твиты в реальном времени по ключевому слову bieber.

Если определенный клиент не готов к приему сообщений (из-за медленной работы сети, других проблем, или из-за того, что он подключен через long polling и находится в середине цикла запрос-ответ), если он не получает ВСЕ твиты,связанные с bieber,то ваше приложение не пострадает.

В этом случае вы можете отправить эти сообщения как нестабильные(изменчивые) сообщения.

Сервер

var io = require('socket.io')(80);

io.on('connection', function (socket) {
  var tweets = setInterval(function () {
    getBieberTweet(function (tweet) {
      socket.volatile.emit('bieber tweet', tweet);
    });
  }, 100);

  socket.on('disconnect', function () {
    clearInterval(tweets);
  });
});

Отправка и получение данных (подтверждений)

Иногда может потребоваться callback, когда клиент подтвердил получение сообщения

Для этого просто передайте функцию в качестве последнего параметра .send или .emit. Более того, когда вы используете .emit, подтверждение делается вами, что означает, что вы также можете передавать данные:

Сервер (app.js)

var io = require('socket.io')(80);

io.on('connection', function (socket) {
  socket.on('ferret', function (name, word, fn) {
    fn(name + ' says ' + word);
  });
});

Клиент (index.html)

<script>
  var socket = io(); // СОВЕТ: io() без аргументов производит автообнаружение
  socket.on('connect', function () { // СОВЕТ: вы можете избежать прослушивания через `connect` и прослушивать события напрямую!
    socket.emit('ferret', 'tobi', 'woot', function (data) { // аргументы отправляются для подтверждения функции
      console.log(data); // 'tobi says woot'
    });
  });
</script>

Широковещательные сообщения

Чтобы отправить широковещательное сообщение (broadcasting), просто добавьте флаг broadcast в вызовы методов emit и send.

Broadcasting - отправка сообщения всем, кроме сокета, который его запускает.

Server

var io = require('socket.io')(80);

io.on('connection', function (socket) {
  socket.broadcast.emit('user connected');
});

Использование в качестве кроссбраузерного WebSocket

Если вам нужно понимание WebSocket, то используйте send и прослушайте событие message:

Сервер (app.js)

var io = require('socket.io')(80);

io.on('connection', function (socket) {
  socket.on('message', function () { });
  socket.on('disconnect', function () { });
});

Клиент (index.html)

<script>
  var socket = io('http://localhost/');
  socket.on('connect', function () {
    socket.send('hi');

    socket.on('message', function (msg) {
      // моё сообщение
    });
  });
</script>

Если вам не важна логика переподключения и тому подобное, посмотрите Engine.IO, который использует Socket.IO и является транспортным уровнем WebSocket.

Комнаты и пространства имен

Пространства имен

SocketIO позволяет вам «именовать» свои сокеты, то есть назначать различные конечные точки (endpoints) или пути (paths).

Это полезная функция, позволяющая минимизировать количество ресурсов (TCP-соединений) и в то же время разделять проблемы в вашем приложении за счет разделения каналов связи.

Пространство имен по умолчанию

Мы называем пространством имен по умолчанию /, и это то, к чему клиенты SocketIO подключаются по умолчанию, и то, которое сервер слушает по умолчанию.

Это пространство имен задается с помощью io.sockets или io:

// оба примера будут генерировать все сокеты, подключенные к`/`
io.sockets.emit('hi', 'everyone');
io.emit('hi', 'everyone'); // краткая форма

Каждое пространство имен генерирует событие connection, которое получает каждый экземпляр Socket в качестве параметра

io.on('connection', function(socket){
  socket.on('disconnect', function(){ });
});

Пользовательские пространства имен

Чтобы настроить собственное пространство имен, вы должны вызвать функцию of на стороне сервера:

const nsp = io.of('/my-namespace');
nsp.on('connection', function(socket){
  console.log('someone connected');
});
nsp.emit('hi', 'everyone!');

На стороне клиента вы подключаете SocketIO к этому пространству имен:

const socket = io('/my-namespace');

ВАЖНО: Пространство имен является частью реализации протокола SocketIO и не связано с фактическим URL-адресом базового транспортного протокола, который по умолчанию равен /socket.io/….

Комнаты

В каждом пространстве имен вы также можете определить произвольные каналы, которые сокеты могут присоединять (join) и покидать (leave).

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

Вы можете вызвать join, чтобы подписать сокет на данный канал:

io.on('connection', function(socket){
  socket.join('some room');
});

А затем используйте to или in (они одинаковы) при трансляции(broadcasting) или генерации(emitting):

io.to('some room').emit('some event');

Чтобы выйти из канала, вы вызываете exit так же, как join.

Комната по умолчанию

Каждый Socket в SocketIO идентифицируется случайным, неопределяемым, уникальным идентификатором Socket#id. Для удобства каждый сокет автоматически присоединяется к комнате, идентифицируемой этим идентификатором.

Это позволяет легко транслировать сообщения на другие сокеты:

io.on('connection', function(socket){
  socket.on('say to someone', function(id, msg){
    socket.broadcast.to(id).emit('my message', msg);
  });
});

Отключение

При отключении сокеты автоматически «покидают» (leave) все каналы, частью которых они были, и с вашей стороны не требуется никаких специальных действий.

Отправка сообщений из внешних процессов

В некоторых случаях вам может потребоваться отправлять события в сокеты в пространствах имен/комнатах вне контекста ваших процессов Socket.IO.

Существует несколько способов решения этой проблемы, например, создание собственного канала для отправки сообщений в процесс.

Чтобы облегчить этот вариант использования, существует два модуля:

Реализация в Redis паттерна Adapter:

const io = require('socket.io')(3000);
const redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));

затем вы можете генерировать (emit) сообщения из любого другого процесса на любой канал

const io = require('socket.io-emitter')({ host: '127.0.0.1', port: 6379 });
setInterval(function(){
  io.emit('time', new Date);
}, 5000);

Логирование и отладка

SocketIO оснащен минималистичной, но чрезвычайно мощной утилитой под названием debug от TJ Holowaychuk.

До версии 1.0 сервер SocketIO по умолчанию записывал все в консоль. Это раздражало многих пользователей (хотя было полезно для других), поэтому теперь по умолчанию запись в консоль отключена.

Основная идея заключается в том, что каждый модуль, используемый SocketIO, предоставляет различные области отладки, которые дают вам представление о внутреннем устройстве. По умолчанию весь вывод скрыт, и вы можете выбрать просмотр сообщений, указав переменную окружения DEBUG (в Node.JS) или свойство localStorage.debug (в браузерах).

Вы можете увидеть демонстрацию работы этого инструмента, кликнув по ссылке.

Доступные области отладки

Лучший способ узнать, какая информация доступна, это использовать *:

DEBUG=* node yourfile.js

или в браузере:

localStorage.debug = '*';

Затем выполните фильтрацию по интересующим вас областям. Вы можете поставить перед префиксом области *, разделив запятой, если их несколько. Например, чтобы увидеть только операторы отладки из клиента socket.io на Node.js, выполните:

DEBUG=socket.io:client* node yourfile.js

Чтобы увидеть все отладочные сообщения от engine и socket.io:

DEBUG=engine,socket.io* node yourfile.js

Шпаргалка по Emit


io.on('connect', onConnect);

function onConnect(socket){

  // отправка клиенту
  socket.emit('hello', 'can you hear me?', 1, 2, 'abc');

  // отправка всем клиентам, кроме отправителя
  socket.broadcast.emit('broadcast', 'hello friends!');

  // отправка всем клиентам комнаты 'game', кроме отправителя
  socket.to('game').emit('nice game', "let's play a game");

  // отправка всем клиентам комнат 'game1' и/или 'game2' , кроме отправителя
  socket.to('game1').to('game2').emit('nice game', "let's play a game (too)");

  // отправка всем клиентам комнаты 'game' , включая отправителя
  io.in('game').emit('big-announcement', 'the game will start soon');

  // отправка всем клиентам пространства имен 'myNamespace', включая отправителя
  io.of('myNamespace').emit('bigger-announcement', 'the tournament will start soon');

  // отправка в определенную комнату в определенном пространстве имен, включая отправителя
  io.of('myNamespace').to('room').emit('event', 'message');

  // отправка на индивидуальный socketid (личное сообщение)
  io.to(`${socketId}`).emit('hey', 'I just met you');

  // ВНИМАНИЕ: `socket.to(socket.id).emit()` НЕ будет работать, как бы мы отправляли сообщение всем в комнату
  // `socket.id`, а не отправителю. Вместо этого, используйте `socket.emit()`.

  // отправка с подтверждением
  socket.emit('question', 'do you think so?', function (answer) {});

  // отправка без сжатия
  socket.compress(false).emit('uncompressed', "that's rough");

  // отправка сообщения, которое может быть отброшено, если клиент не готов к приему сообщений
  socket.volatile.emit('maybe', 'do you really need it?');

  // указание, имеют ли данные для отправки двоичные данные
  socket.binary(false).emit('what', 'I have no binaries!');

  // отправка всем клиентам на этом узле (при использовании нескольких узлов)
  io.local.emit('hi', 'my lovely babies');

  // отправка всем подключенным клиентам
  io.emit('an event sent to all connected clients');

};

Важно: Следующие события зарезервированы и не должны использоваться в качестве имен событий вашим приложением:

  • error
  • connect
  • disconnect
  • disconnecting
  • newListener
  • removeListener
  • ping
  • pong

About

Перевод документации и API socket.io на русский язык

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published