WebSocket¶
WebSocket - это протокол передачи данных, основанный на протоколе TCP обеспечивающий обмен сообщениями между клиентом и сервером в режиме реального времени.
Протокол WebSocket¶
Для установления соединения по WebSocket клиентская сторона сперва отправляет используя протокол HTTP специальные заголовки Upgrade
и Connection
, тем самым говоря, что она хочет перейти на общение по WebSocket
. А сервер уже сам решает, разрешать установку соединения или нет.
Обмен сообщениями между сервером и клиентом осуществляется с помощью специальных пакетов, называемых фреймами. Выделяют два типа фреймов:
- Управляющие данными (посылают данные);
- Управляющие соединением (проверяют установку соединения через PING или закрывают его).
Node.js и socket.io¶
Для использования в Node.js WebSocket необходимо установить npm модуль socket.io.
1 |
|
Рассмотрим пример.
app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
|
index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
Для подключения WebSocket на клиентской стороне используется модуль socket.io-client
, экземпляру которого передается адрес сервера, с которым необходимо установить соединение по WebSocket.
При установке соединения между клиентом и сервером Node.js по WebSocket генерируется событие connection
, которое обрабатывается с помощью метода on()
модуля socket.io
. Передаваемая вторым параметром методу on()
callback-функция единственным параметром принимает экземпляр соединения (далее просто сокет).
1 |
|
Каждое соединение имеет свой уникальный идентификатор, зная который можно отправить сообщение конкретному клиенту (см. в примере маршрут /client/:id
).
При разрыве соединения генерируется событие disconnect
. Соединение разрывается, когда пользователь закрывает вкладку или когда сервер вызывает у сокета метод disconnect()
.
1 |
|
Для отправки данных от сервера Node.js к клиенту (и наоборот), используется метод emit()
, которые принимает следующие параметры:
- имя события;
- данные, которые необходимо отправить (могут быть отправлены в виде REST-аргументов);
- callback-функция (передается последним параметром), которая будет вызвана, когда вторая сторона получит сообщение.
Обработка отправляемых данных на стороне получателя происходит с использованием уже знакомого метода on()
, первым параметром принимающего имя события, указанного в emit()
, вторым - callback-функцию с переданными данными в качестве ее параметров.
1 2 3 4 5 6 7 8 9 10 11 |
|
Для отправки данных всем клиентам, используйте метод emit()
применительно к объекту io.sockets
.
1 |
|
Чтобы узнать текущее количество соединений, используйте метод clients()
, вызываемый применительно к свойству sockets
экземпляра модуля socket.io
(см. в примере маршрут /clients-count
).
В качестве необязательного параметра методу clients()
можно передать имя "комнаты", количество соединений для который вы хотите узнать.
Пространства и "комнаты"¶
В протоколе WebSocket существуют такие понятия, как пространства и "комнаты". По умолчанию посылаемые данные отправляются всем сокетам, но принимают эти данные лишь некоторые из них. Получается, что в определенные моменты времени будет установлено избыточное количество соединений. Чтобы избежать этого, используйте пространства.
Пространства позволяют изолировать одни сокеты от других.
app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
1 |
|
В приведенном примере с помощью метода of()
на сервере определяются два пространства: /users
и /orders
. На клиентской стороне подключение к тому или иному пространству происходит в зависимости от текущего маршрута. Таким образом, при отправке данных, например, из пространства /users
, об этом будут оповещены только сокеты этого пространства. По умолчанию все сокеты находятся в пространстве /
.
Также и в пределах пространства можно распределять сокеты по так называемым "комнатам".
1 2 3 |
|
Чтобы отнести сокет к определенной "комнате" используется метод пространства join()
, который принимает имя "комнаты" (задается пользователем модуля socket.io
). Для вынесения сокета из комнаты используйте метод leave()
.
Отправка данных в "комнату" осуществляется с помощью метода to()
.
1 |
|
Обработка инициируемых в пределах "комнаты" событий осуществляется с использованием метода in()
.
1 2 3 |
|