Экземпляр Socket (серверная сторона)
Класс Socket является основным классом для взаимодействия с клиентом. Он наследует все методы Node.js EventEmitter, такие как emit, on, once или removeListener.
Помимо этого:
Экземпляр 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
Это событие срабатывает в экземпляре 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