Spec-Zone.ru › Socket.IO 3

Как это работает

Двунаправленный канал между сервером Socket.IO (Node.js) и клиентом Socket.IO (браузер, Node.js или другой язык программирования) устанавливается с помощью соединения WebSocket, если это возможно, а в качестве резервного варианта используется HTTP-долгое опроса.

База кода Socket.IO разделена на два отдельных слоя:

  • низкоуровневая инфраструктура: то, что мы называем Engine.IO, движок внутри Socket.IO
  • высокоуровневый API: сам Socket.IO

Engine.IO

Engine.IO отвечает за установление низкоуровневого соединения между сервером и клиентом. Он обрабатывает:

  • различные передачи и механизм обновления
  • обнаружение отключения

Исходный код можно найти здесь:

  • сервер: https://github.com/socketio/engine.io
  • клиент: https://github.com/socketio/engine.io-client
  • парсер: https://github.com/socketio/engine.io-parser
  • описание протокола: https://github.com/socketio/engine.io-protocol

Передачи

В настоящее время реализованы две передачи:

  • HTTP-долгое опроса
  • WebSocket

HTTP-долгое опроса

Передача HTTP-долгое опроса (также просто называемая «опрос») состоит из последовательных HTTP-запросов:

  • долго выполняющиеся GET запросы для получения данных с сервера
  • кратковременные POST запросы для отправки данных на сервер

Successive HTTP requests

Из-за особенностей передачи последовательные отправки данных могут быть объединены и отправлены в рамках одного HTTP-запроса.

WebSocket

Передача WebSocket состоит, собственно, в соединении WebSocket, которое обеспечивает двусторонний и низкозадерженный канал связи между сервером и клиентом.

Из-за особенностей передачи каждое отправление данных отправляется в отдельном кадре WebSocket (некоторые отправки данных могут даже привести к двум различным кадрам WebSocket, больше информации здесь).

Handshake

В начале соединения Engine.IO сервер отправляет некоторую информацию:

{
  "sid": "FSDjX-WRwSA4zTZMALqx",
  "upgrades": ["websocket"],
  "pingInterval": 25000,
  "pingTimeout": 5000
}
  • sid — это идентификатор сессии, он должен быть включен в sid параметр запроса во всех последующих HTTP-запросах
  • массив upgrades содержит список всех «лучших» передач, поддерживаемых сервером
  • значения pingInterval и pingTimeout используются в механизме проверки работоспособности соединения

Механизм обновления

По умолчанию клиент устанавливает соединение с помощью передачи HTTP-долгое опроса.

Но почему?

Хотя WebSocket является лучшим способом для двусторонней связи, опыт показал, что не всегда возможно установить соединение WebSocket из-за корпоративных прокси-серверов, личных брандмауэров, антивирусного программного обеспечения...

С точки зрения пользователя неудачное соединение WebSocket может привести к ожиданию до 10 секунд, прежде чем приложение начнёт обмен данными в реальном времени. Это негативно сказывается на пользовательском опыте.

Подводя итог, Engine.IO фокусируется на надёжности и пользовательском опыте в первую очередь, а на незначительных потенциальных улучшениях UX и увеличении производительности сервера — во вторую.

Для обновления клиент выполнит следующие действия:

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

Вы можете проверить это в мониторе сети своего браузера:

Successful upgrade

  1. handshake (содержит идентификатор сессии — здесь, zBjrh...AAAK — который используется в последующих запросах)
  2. отправка данных (HTTP-долгое опроса)
  3. получение данных (HTTP-долгое опроса)
  4. обновление (WebSocket)
  5. получение данных (HTTP-долгое опроса, закрывается после того, как соединение WebSocket в пункте 4. успешно установлено)

Обнаружение отключения

Соединение Engine.IO считается закрытым, когда:

  • один HTTP-запрос (GET или POST) завершается неудачно (например, при остановке сервера)
  • соединение WebSocket закрывается (например, при закрытии вкладки в браузере)
  • socket.disconnect() вызывается на стороне сервера или клиента

Также существует механизм проверки работоспособности соединения, который проверяет, что соединение между сервером и клиентом всё ещё активно:

С заданным интервалом (значение pingInterval отправленное в handshake) сервер отправляет пакет PING, и у клиента есть несколько секунд (значение pingTimeout ) чтобы отправить пакет PONG обратно. Если сервер не получает пакет PONG обратно, он считает, что соединение закрыто. Аналогично, если клиент не получает пакет PING в течение pingInterval + pingTimeout, он считает, что соединение закрыто.

Причины отключения перечислены здесь (на стороне сервера) и здесь (на стороне клиента).

Socket.IO

Socket.IO предоставляет дополнительные возможности по сравнению с соединением Engine.IO:

  • автоматическое переподключение
  • буферизация пакетов
  • подтверждения
  • распространение всем клиентам или подмножеству клиентов (называемое «Комната»)
  • мультиплексирование (называемое «Пространство имён»)

Исходный код можно найти здесь:

  • сервер: https://github.com/socketio/socket.io
  • клиент: https://github.com/socketio/socket.io-client
  • парсер: https://github.com/socketio/socket.io-parser
  • описание протокола: https://github.com/socketio/socket.io-protocol

© 2014–2021 Automattic
Licensed under the MIT License.
https://socket.io/docs/v3/how-it-works

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API