Spec-Zone.ru › Socket.IO 4

Комнаты

Комната — это произвольный канал, к которому сокеты могут join и leave. Его можно использовать для трансляции событий подмножеству клиентов:

Broadcasting to all clients in a room

Обратите внимание, что комнаты — это понятие только сервера (т.е. клиент не имеет доступа к списку комнат, к которым он присоединился).

Присоединение и выход

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

io.on("connection", (socket) => {
  socket.join("some room");
});

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

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

Вы можете отправлять события сразу в несколько комнат:

io.to("room1").to("room2").to("room3").emit("some event");

В этом случае выполняется операция объединения: каждый сокет, который находится хотя бы в одной из комнат, получит событие один раз (даже если сокет находится в двух или более комнатах).

Вы также можете транслировать событие в комнату из данного сокета:

io.on("connection", (socket) => {
  socket.to("some room").emit("some event");
});

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

Broadcasting to all clients in a room excepting the sender

Чтобы выйти из канала, вызывается leave аналогично join.

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

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

Это упрощает реализацию личных сообщений:

io.on("connection", (socket) => {
  socket.on("private message", (anotherSocketId, msg) => {
    socket.to(anotherSocketId).emit("private message", socket.id, msg);
  });
});

Примеры использования

  • трансляция данных на каждое устройство/вкладку данного пользователя
io.on("connection", async (socket) => {
  const userId = await fetchUserId(socket);

  socket.join(userId);

  // and then later
  io.to(userId).emit("hi");
});
  • отправка уведомлений об определенном объекте
io.on("connection", async (socket) => {
  const projects = await fetchProjects(socket);

  projects.forEach(project => socket.join("project:" + project.id));

  // and then later
  io.to("project:4321").emit("project updated");
});

Отключение

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

Вы можете получить список комнат, в которых находился сокет, прослушивая событие disconnecting:

io.on("connection", socket => {
  socket.on("disconnecting", () => {
    console.log(socket.rooms); // the Set contains at least the socket ID
  });

  socket.on("disconnect", () => {
    // socket.rooms.size === 0
  });
});

С несколькими серверами Socket.IO

Как и при глобальной трансляции, трансляция в комнаты также работает с несколькими серверами Socket.IO.

Вам просто нужно заменить адаптер по умолчанию (Adapter) адаптером Redis. Дополнительная информация об этом здесь.

Broadcasting to all clients in a room with Redis

Подробности реализации

Функция "комнаты" реализована с помощью компонента, который мы называем адаптером. Этот адаптер — это компонент на стороне сервера, который отвечает за:

  • хранение отношений между экземплярами сокетов и комнатами
  • трансляцию событий всем (или подмножеству) клиентам

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

В основном, он состоит из двух ES6 карт:

  • sids: Map<SocketId, Set<Room>>
  • rooms: Map<Room, Set<SocketId>>

Вызов socket.join("the-room") приведет к:

  • в карте ̀sids добавлению "the-room" в множество, идентифицированное идентификатором сокета
  • в карте rooms добавлению идентификатора сокета в множество, идентифицированное строкой "the-room"

Затем эти две карты используются при трансляции:

  • трансляция всем сокетам (io.emit()) проходит по карте sids, и пакет отправляется всем сокетам
  • трансляция в заданную комнату (io.to("room21").emit()) проходит по множеству в карте rooms, и пакет отправляется всем соответствующим сокетам

Доступ к этим объектам можно получить следующим образом:

// main namespace
const rooms = io.of("/").adapter.rooms;
const sids = io.of("/").adapter.sids;

// custom namespace
const rooms = io.of("/my-namespace").adapter.rooms;
const sids = io.of("/my-namespace").adapter.sids;

Примечания:

  • эти объекты не предназначены для прямого изменения, вы всегда должны использовать socket.join(...) и socket.leave(...).
  • в настройке с несколькими серверами объекты rooms и sids не разделяются между серверами Socket.IO (комната может существовать только на одном сервере, а не на другом).

События комнат

Начиная с socket.io@3.1.0, базовый адаптер будет генерировать следующие события:

  • create-room (аргумент: комната)
  • delete-room (аргумент: комната)
  • join-room (аргумент: комната, id)
  • leave-room (аргумент: комната, id)

Пример:

io.of("/").adapter.on("create-room", (room) => {
  console.log(`room ${room} was created`);
});

io.of("/").adapter.on("join-room", (room, id) => {
  console.log(`socket ${id} has joined room ${room}`);
});

© 2014–2021 Automattic
Licensed under the MIT License.
https://socket.io/docs/v4/rooms

Spec-Zone.ru

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