Spec-Zone.ru › Socket.IO 4

Экземпляр Socket (серверная сторона)

Класс Socket является основным классом для взаимодействия с клиентом. Он наследует все методы Node.js EventEmitter, такие как emit, on, once или removeListener.

Bidirectional communication between server and client

Помимо этого:

  • отправка и прослушивание событий
  • рассылка событий
  • присоединение и выход из комнат

Экземпляр Socket имеет несколько атрибутов, которые могут быть полезны в вашем приложении:

Socket#id

Каждое новое подключение получает случайный идентификатор из 20 символов.

Этот идентификатор синхронизирован со значением на стороне клиента.

// server-side
io.on("connection", (socket) => {
  console.log(socket.id); // ojIckSD2jqNzOqIrAGzL
});

// client-side
socket.on("connect", () => {
  console.log(socket.id); // ojIckSD2jqNzOqIrAGzL
});

При создании Socket присоединяется к комнате, идентифицируемой его собственным id, что позволяет использовать его для частных сообщений:

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

Примечание: вы не можете перезаписать этот идентификатор, так как он используется в нескольких частях кода Socket.IO.

Socket#handshake

Этот объект содержит подробности о рукопожатии, которое происходит в начале сессии Socket.IO.

{
  headers: /* the headers of the initial request */
  query: /* the query params of the initial request */
  auth: /* the authentication payload */
  time: /* the date of creation (as string) */
  issued: /* the date of creation (unix timestamp) */
  url: /* the request URL string */
  address: /* the ip of the client */
  xdomain: /* whether the connection is cross-domain */
  secure: /* whether the connection is secure */
}

Пример:

{
  "headers": {
    "user-agent": "xxxx",
    "accept": "*/*",
    "host": "example.com",
    "connection": "close"
  },
  "query": {
    "EIO": "4",
    "transport": "polling",
    "t": "NNjNltH"
  },
  "auth": {
    "token": "123"
  },
  "time": "Sun Nov 22 2020 01:33:46 GMT+0100 (Central European Standard Time)",
  "issued": 1606005226969,
  "url": "/socket.io/?EIO=4&transport=polling&t=NNjNltH",
  "address": "::ffff:1.2.3.4",
  "xdomain": false,
  "secure": true
}

Socket#rooms

Это ссылка на комнаты, в которых в данный момент находится Socket.

io.on("connection", (socket) => {
  console.log(socket.rooms); // Set { <socket.id> }
  socket.join("room1");
  console.log(socket.rooms); // Set { <socket.id>, "room1" }
});

Socket#data

Произвольный объект, который можно использовать совместно с методом fetchSockets():

// server A
io.on("connection", (socket) => {
  socket.data.username = "alice";
});

// server B
const sockets = await io.fetchSockets();
console.log(sockets[0].data.username); // "alice"

Дополнительная информация здесь.

Socket#conn

Ссылка на сокет Engine.IO ниже (см. здесь).

io.on("connection", (socket) => {
  console.log("initial transport", socket.conn.transport.name); // prints "polling"

  socket.conn.once("upgrade", () => {
    // called when the transport is upgraded (i.e. from HTTP long-polling to WebSocket)
    console.log("upgraded transport", socket.conn.transport.name); // prints "websocket"
  });

  socket.conn.on("packet", ({ type, data }) => {
    // called for each packet received
  });

  socket.conn.on("packetCreate", ({ type, data }) => {
    // called for each packet sent
  });

  socket.conn.on("drain", () => {
    // called when the write buffer is drained
  });

  socket.conn.on("close", (reason) => {
    // called when the underlying connection is closed
  });
});

Дополнительные атрибуты

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

// in a middleware
io.use(async (socket, next) => {
  try {
    const user = await fetchUser(socket);
    socket.user = user;
  } catch (e) {
    next(new Error("unknown user"));
  }
});

io.on("connection", (socket) => {
  console.log(socket.user);

  // in a listener
  socket.on("set username", (username) => {
    socket.username = username;
  });
});

Средства обработки Socket

Эти средства обработки похожи на обычные средства обработки, за исключением того, что они вызываются для каждого входящего пакета:

socket.use(([event, ...args], next) => {
  // do something with the packet (logging, authorization, rate limiting...)
  // do not forget to call next() at the end
  next();
});

Метод next также можно вызвать с объектом ошибки. В этом случае событие не достигнет зарегистрированных обработчиков событий, а вместо этого будет отправлено событие error.

io.on("connection", (socket) => {
  socket.use(([event, ...args], next) => {
    if (isUnauthorized(event)) {
      return next(new Error("unauthorized event"));
    }
    next();
  });

  socket.on("error", (err) => {
    if (err && err.message === "unauthorized event") {
      socket.disconnect();
    }
  });
});

Примечание: эта функция существует только на серверной стороне. Для клиентской стороны вы можете быть заинтересованы в глобальных обработчиках событий.

События

На серверной стороне экземпляр Socket отправляет два специальных события:

  • disconnect
  • disconnecting

disconnect

Это событие срабатывает в экземпляре Socket при отключении.

io.on("connection", (socket) => {
  socket.on("disconnect", (reason) => {
    // ...
  });
});

Вот список возможных причин:

Причина Описание
server namespace disconnect Сокет был принудительно отключен с помощью socket.disconnect().
client namespace disconnect Клиент вручную отключил сокет, используя socket.disconnect().
server shutting down Сервер, собственно, завершается.
ping timeout Клиент не отправил пакет PONG в течение pingTimeout задержки.
transport close Подключение было закрыто (например, пользователь потерял соединение или сеть изменилась с WiFi на 4G).
transport error Подключение столкнулось с ошибкой.
parse error Сервер получил недопустимый пакет от клиента.
forced close Сервер получил недопустимый пакет от клиента.
forced server close Клиент не присоединился к именованному пространству вовремя (см. параметр connectTimeout) и был принудительно закрыт.

disconnecting

Это событие аналогично disconnect, но срабатывает немного раньше, когда множество Socket#rooms еще не пустое.

io.on("connection", (socket) => {
  socket.on("disconnecting", (reason) => {
    for (const room of socket.rooms) {
      if (room !== socket.id) {
        socket.to(room).emit("user has left", socket.id);
      }
    }
  });
});

Примечание: эти события, вместе с connect, connect_error, newListener и removeListener, являются специальными событиями, которые не следует использовать в вашем приложении:

// BAD, will throw an error
socket.emit("disconnect");

Полный API

Полный API, предоставляемый экземпляром Socket, можно найти здесь.

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

Spec-Zone.ru

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