Spec-Zone.ru › Socket.IO 4

Серверный API

Сервер

Server in the class diagram for the server

Связанные страницы документации:

  • установка
  • инициализация
  • детали экземпляра сервера

new Server(httpServer[, options])

  • httpServer <http.Server> | <https.Server>
  • options <Object>
import { createServer } from "http";
import { Server } from "socket.io";

const httpServer = createServer();
const io = new Server(httpServer, {
  // options
});

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

httpServer.listen(3000);

Полный список доступных параметров можно найти здесь.

new Server(port[, options])

  • port <number>
  • options <Object>
import { Server } from "socket.io";

const io = new Server(3000, {
  // options
});

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

Полный список доступных параметров можно найти здесь.

new Server(options)

  • options <Object>
import { Server } from "socket.io";

const io = new Server({
  // options
});

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

io.listen(3000);

Полный список доступных параметров можно найти здесь.

server.sockets

  • <Namespace>

Псевдоним для основного пространства имён (/).

io.sockets.emit("hi", "everyone");
// is equivalent to
io.of("/").emit("hi", "everyone");

server.serveClient([value])

  • value <boolean>
  • Возвращает <Server> | <boolean>

Если value равно true, присоединённый сервер будет обслуживать файлы клиента. По умолчанию true. Этот метод не имеет эффекта после вызова listen. Если аргументы не переданы, этот метод возвращает текущее значение.

import { Server } from "socket.io";

const io = new Server();

io.serveClient(false);

io.listen(3000);

server.path([value])

  • value <string>
  • Возвращает <Server> | <string>

Устанавливает путь value, под которым engine.io и статические файлы будут обслуживаться. По умолчанию /socket.io/. Если аргументы не переданы, этот метод возвращает текущее значение.

import { Server } from "socket.io";

const io = new Server();

io.path("/myownpath/");

Значение path должно совпадать со значением на стороне клиента:

import { io } from "socket.io-client";

const socket = io({
  path: "/myownpath/"
});

server.adapter([value])

  • value <Adapter>
  • Возвращает <Server> | <Adapter>

Устанавливает адаптер value. По умолчанию экземпляр Adapter, который поставляется с socket.io, основанный на памяти. См. socket.io-adapter. Если аргументы не переданы, этот метод возвращает текущее значение.

import { Server } from "socket.io"; 
import { createAdapter } from "@socket.io/redis-adapter";
import { createClient } from "redis";

const io = new Server();

const pubClient = createClient({ host: "localhost", port: 6379 });
const subClient = pubClient.duplicate();

io.adapter(createAdapter(pubClient, subClient));

// redis@3
io.listen(3000);

// redis@4
Promise.all([pubClient.connect(), subClient.connect()]).then(() => {
  io.listen(3000);
});

server.attach(httpServer[, options])

  • httpServer <http.Server> | <https.Server>
  • options <Object>

Присоединяет Server к httpServer с предоставленными options.

import { createServer } from "http";
import { Server } from "socket.io";

const httpServer = createServer();
const io = new Server();

io.attach(httpServer);

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

httpServer.listen(3000);

server.attach(port[, options])

  • port <number>
  • options <Object>

Присоединяет Server к указанному port с предоставленными options.

import { Server } from "socket.io";

const io = new Server();

io.attach(3000);

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

server.attachApp(app[, options])

  • app <uws.App>
  • options <Object>

Присоединяет сервер Socket.IO к приложению µWebSockets.js:

import { App } from "uWebSockets.js";
import { Server } from "socket.io";

const app = new App();
const io = new Server();

io.attachApp(app);

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

app.listen(3000, (token) => {
  if (!token) {
    console.warn("port already in use");
  }
});

server.listen(httpServer[, options])

Синоним server.attach(httpServer[, options]).

server.listen(port[, options])

Синоним server.attach(port[, options]).

server.on(eventName, listener)

Унаследовано от класса EventEmitter.

  • eventName <string> | <symbol>
  • listener <Function>
  • Возвращает <Server>

Добавляет функцию listener в конец массива обработчиков для события с именем eventName.

Доступные события:

  • connection
  • new_namespace
  • любое пользовательское событие из метода serverSideEmit
io.on("connection", (socket) => {
  // ...
});

server.bind(engine)

  • engine <engine.Server>
  • Возвращает <Server>

Только для расширенного использования. Связывает сервер со специфическим экземпляром Server engine.io (или совместимым API).

import { Server } from "socket.io";
import { Server as Engine } from "engine.io";

const engine = new Engine();
const io = new Server();

io.bind(engine);

engine.listen(3000);

server.onconnection(socket)

  • socket <engine.Socket>
  • Возвращает <Server>

Только для расширенного использования. Создаёт нового клиента socket.io из входящего Socket engine.io (или совместимого API).

import { Server } from "socket.io";
import { Server as Engine } from "engine.io";

const engine = new Engine();
const io = new Server();

engine.on("connection", (socket) => {
  io.onconnection(socket);
});

engine.listen(3000);

server.of(nsp)

  • nsp <string> | <RegExp> | <Function>
  • Возвращает <Namespace>

Инициализирует и возвращает заданное Namespace по идентификатору пути nsp. Если пространство имён уже инициализировано, оно возвращается сразу.

const adminNamespace = io.of("/admin");

Также можно указать регулярное выражение или функцию, чтобы создать пространство имён динамически:

const dynamicNsp = io.of(/^\/dynamic-\d+$/).on("connection", (socket) => {
  const newNamespace = socket.nsp; // newNamespace.name === "/dynamic-101"

  // broadcast to all clients in the given sub-namespace
  newNamespace.emit("hello");
});

// client-side
const socket = io("/dynamic-101");

// broadcast to all clients in each sub-namespace
dynamicNsp.emit("hello");

// use a middleware for each sub-namespace
dynamicNsp.use((socket, next) => { /* ... */ });

С функцией:

io.of((name, query, next) => {
  // the checkToken method must return a boolean, indicating whether the client is able to connect or not.
  next(null, checkToken(query.token));
}).on("connection", (socket) => { /* ... */ });

server.close([callback])

  • callback <Function>

Закрывает сервер Socket.IO и отключает всех клиентов. Аргумент callback (опционально) будет вызван при закрытии всех соединений.

Это также закрывает базовый HTTP-сервер.

import { createServer } from "http";
import { Server } from "socket.io";

const PORT = 3030;
const io = new Server(PORT);

io.close();

const httpServer = createServer();

httpServer.listen(PORT); // PORT is free to use

io.attach(httpServer);

Закрытие только базового HTTP-сервера недостаточно, так как это только предотвращает принятие новых подключений, но клиенты, подключенные через WebSocket, не будут отключены сразу.

Ссылка: https://nodejs.org/api/http.html#serverclosecallback

server.engine

Ссылка на базовый сервер Engine.IO. См. здесь.

server.socketsJoin(rooms)

Добавлено в версии 4.0.0

Псевдоним для io.of("/").socketsJoin(rooms).

// make all Socket instances join the "room1" room
io.socketsJoin("room1");

// make all Socket instances in the "room1" room join the "room2" and "room3" rooms
io.in("room1").socketsJoin(["room2", "room3"]);

// this also works with a single socket ID
io.in(theSocketId).socketsJoin("room1");

См. здесь.

server.socketsLeave(rooms)

Добавлено в версии 4.0.0

Псевдоним для io.of("/").socketsLeave(rooms).

// make all Socket instances leave the "room1" room
io.socketsLeave("room1");

// make all Socket instances in the "room1" room leave the "room2" and "room3" rooms
io.in("room1").socketsLeave(["room2", "room3"]);

// this also works with a single socket ID
io.in(theSocketId).socketsLeave("room1");

См. здесь.

server.disconnectSockets([close])

Добавлено в версии 4.0.0

Псевдоним для io.of("/").disconnectSockets(close).

// make all Socket instances disconnect
io.disconnectSockets();

// make all Socket instances in the "room1" room disconnect (and close the low-level connection)
io.in("room1").disconnectSockets(true);

См. здесь.

server.fetchSockets()

Добавлен в v4.0.0

Псевдоним для io.of("/").fetchSocket().

// return all Socket instances of the main namespace
const sockets = await io.fetchSockets();

// return all Socket instances in the "room1" room of the main namespace
const sockets = await io.in("room1").fetchSockets();

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

io.on("connection", (socket) => {
  const userId = computeUserId(socket);

  socket.join(userId);

  socket.on("disconnect", async () => {
    const sockets = await io.in(userId).fetchSockets();
    if (socket.length === 0) {
      // no more active connections for the given user
    }
  });
});

См. здесь.

server.serverSideEmit(eventName[, ...args][, ack])

Добавлен в v4.1.0

Псевдоним для: io.of("/").serverSideEmit(/* ... */);

Событие: connection

  • socket (Сокет) подключение сокета с клиентом

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

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

Событие: connect

Синоним события Event: "connection".

Событие: new_namespace

  • namespace Namespace

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

io.on("new_namespace", (namespace) => {
  // ...
});

Это может быть полезно, например:

  • для присоединения общего среднего слоя ко всем пространствам имен
io.on("new_namespace", (namespace) => {
  namespace.use(myMiddleware);
});
  • для отслеживания динамически созданных пространств имен
io.of(/\/nsp-\w+/);

io.on("new_namespace", (namespace) => {
  console.log(namespace.name);
});

Пространство имен

Namespace in the class diagram for the server

Представляет собой пул сокетов, подключенных в заданном контексте, определяемом путем (например: /chat).

Дополнительную информацию можно найти здесь.

namespace.name

  • <string>

Свойство идентификатора пространства имен.

namespace.sockets

  • Map<SocketId, Socket>

Карта экземпляров Socket, подключенных к этому пространству имен.

// number of sockets in this namespace (on this node)
const socketCount = io.of("/admin").sockets.size;

namespace.adapter

  • <Adapter>

Используемый "адаптер" для пространства имен.

Примечание: адаптер основного пространства имен можно получить с помощью io.of("/").adapter.

Дополнительную информацию можно найти здесь.

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

namespace.to(room)

История
Версия Изменения
v4.0.0 Разрешение передачи массива комнат.
v1.0.0 Первоначальная реализация.
  • room <string> | <string[]>
  • Возвращает BroadcastOperator для цепочки вызовов

Устанавливает модификатор для последующей отправки события, что событие будет транслироваться только клиентам, которые присоединились к заданной room.

Для отправки события в несколько комнат можно вызвать to несколько раз.

const io = require("socket.io")();
const adminNamespace = io.of("/admin");

adminNamespace.to("level1").emit("an event", { some: "data" });

// multiple rooms
io.to("room1").to("room2").emit(/* ... */);

// or with an array
io.to(["room1", "room2"]).emit(/* ... */);

namespace.in(room)

Добавлен в v1.0.0

Синоним для namespace.to(room).

namespace.except(rooms)

Добавлен в v4.0.0

  • rooms <string> | <string[]>
  • Возвращает BroadcastOperator

Устанавливает модификатор для последующей отправки события, что событие будет транслироваться только клиентам, которые не присоединились к заданным rooms.

// to all clients except the ones in "room1"
io.except("room1").emit(/* ... */);

// to all clients in "room2" except the ones in "room3"
io.to("room2").except("room3").emit(/* ... */);

namespace.emit(eventName[, ...args])

  • eventName <string> | <symbol>
  • args any[]
  • Возвращает true

Отправляет событие всем подключенным клиентам в данном пространстве имен.

io.emit("an event sent to all connected clients"); // main namespace

const chat = io.of("/chat");
chat.emit("an event sent to all connected clients in chat namespace");

Начиная с версии 4.5.0, теперь можно использовать подтверждения при трансляции:

io.of("/chat").timeout(10000).emit("some-event", (err, responses) => {
  if (err) {
    // some clients did not acknowledge the event in the given delay
  } else {
    console.log(responses); // one response per client
  }
});

namespace.timeout(value)

Добавлен в v4.5.0

  • value <number>
  • Возвращает BroadcastOperator

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

io.of("/chat").timeout(10000).emit("some-event", (err, responses) => {
  if (err) {
    // some clients did not acknowledge the event in the given delay
  } else {
    console.log(responses); // one response per client
  }
});

namespace.allSockets()

  • Возвращает Promise<Set<SocketId>>

Возвращает список идентификаторов сокетов, подключенных к этому пространству имен (по всем узлам, если применимо).

// all sockets in the main namespace
const ids = await io.allSockets();

// all sockets in the main namespace and in the "user:1234" room
const ids = await io.in("user:1234").allSockets();

// all sockets in the "chat" namespace
const ids = await io.of("/chat").allSockets();

// all sockets in the "chat" namespace and in the "general" room
const ids = await io.of("/chat").in("general").allSockets();

namespace.use(fn)

  • fn <Function>

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

Ошибки, переданные обратным вызовам среднего слоя, отправляются как специальные connect_error пакеты клиентам.

// server-side
io.use((socket, next) => {
  const err = new Error("not authorized");
  err.data = { content: "Please retry later" }; // additional details
  next(err);
});

// client-side
socket.on("connect_error", err => {
  console.log(err instanceof Error); // true
  console.log(err.message); // not authorized
  console.log(err.data); // { content: "Please retry later" }
});

Дополнительную информацию можно найти здесь.

namespace.socketsJoin(rooms)

Добавлен в v4.0.0

  • rooms <string> | <string[]>
  • Возвращает void

Присоединяет соответствующие экземпляры Socket к указанным комнатам:

// make all Socket instances join the "room1" room
io.socketsJoin("room1");

// make all Socket instances in the "room1" room join the "room2" and "room3" rooms
io.in("room1").socketsJoin(["room2", "room3"]);

// make all Socket instances in the "room1" room of the "admin" namespace join the "room2" room
io.of("/admin").in("room1").socketsJoin("room2");

// this also works with a single socket ID
io.in(theSocketId).socketsJoin("room1");

Дополнительную информацию можно найти здесь.

namespace.socketsLeave(rooms)

Добавлен в v4.0.0

  • rooms <string> | <string[]>
  • Возвращает void

Выводит соответствующие экземпляры Socket из указанных комнат:

// make all Socket instances leave the "room1" room
io.socketsLeave("room1");

// make all Socket instances in the "room1" room leave the "room2" and "room3" rooms
io.in("room1").socketsLeave(["room2", "room3"]);

// make all Socket instances in the "room1" room of the "admin" namespace leave the "room2" room
io.of("/admin").in("room1").socketsLeave("room2");

// this also works with a single socket ID
io.in(theSocketId).socketsLeave("room1");

namespace.disconnectSockets([close])

Добавлен в v4.0.0

  • close <boolean> нужно ли закрыть основное соединение
  • Возвращает void

Отключает соответствующие экземпляры Socket.

// make all Socket instances disconnect
io.disconnectSockets();

// make all Socket instances in the "room1" room disconnect (and discard the low-level connection)
io.in("room1").disconnectSockets(true);

// make all Socket instances in the "room1" room of the "admin" namespace disconnect
io.of("/admin").in("room1").disconnectSockets();

// this also works with a single socket ID
io.of("/admin").in(theSocketId).disconnectSockets();

namespace.fetchSockets()

Добавлен в v4.0.0

  • Возвращает Socket[] | RemoteSocket[]

Возвращает соответствующие экземпляры Socket:

// return all Socket instances in the main namespace
const sockets = await io.fetchSockets();

// return all Socket instances in the "room1" room of the main namespace
const sockets = await io.in("room1").fetchSockets();

// return all Socket instances in the "room1" room of the "admin" namespace
const sockets = await io.of("/admin").in("room1").fetchSockets();

// this also works with a single socket ID
const sockets = await io.in(theSocketId).fetchSockets();

Переменная sockets в примере выше — массив объектов, представляющих подмножество обычного класса Socket:

for (const socket of sockets) {
  console.log(socket.id);
  console.log(socket.handshake);
  console.log(socket.rooms);
  console.log(socket.data);
  socket.emit(/* ... */);
  socket.join(/* ... */);
  socket.leave(/* ... */);
  socket.disconnect(/* ... */);
}

Атрибут data — произвольный объект, который можно использовать для обмена информацией между серверами Socket.IO:

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

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

Важно: этот метод (и socketsJoin, socketsLeave и disconnectSockets также) совместим с адаптером Redis (начиная с socket.io-redis@6.1.0). Это означает, что они будут работать между серверами Socket.IO.

namespace.serverSideEmit(eventName[, ...args][, ack])

Добавлен в v4.1.0

  • eventName <string>
  • args <any[]>
  • ack <Function>
  • Возвращает true

Отправляет сообщение другим серверам Socket.IO в кластере.

Синтаксис:

io.serverSideEmit("hello", "world");

И со стороны получателя:

io.on("hello", (arg1) => {
  console.log(arg1); // prints "world"
});

Поддерживаются и подтверждения:

// server A
io.serverSideEmit("ping", (err, responses) => {
  console.log(responses[0]); // prints "pong"
});

// server B
io.on("ping", (cb) => {
  cb("pong");
});

Примечания:

  • строки connection, connect и new_namespace зарезервированы и не могут использоваться в вашем приложении.
  • можно отправлять любое количество аргументов, но бинарные структуры в настоящее время не поддерживаются (массив аргументов будет JSON.stringify-ом)

Пример:

io.serverSideEmit("hello", "world", 1, "2", { 3: "4" });
  • обратный вызов подтверждения может быть вызван с ошибкой, если другие серверы Socket.IO не отвечают в течение заданного времени
io.serverSideEmit("ping", (err, responses) => {
  if (err) {
    // at least one Socket.IO server has not responded
    // the 'responses' array contains all the responses already received though
  } else {
    // success! the 'responses' array contains one object per other Socket.IO server in the cluster
  }
});

Событие: 'connection'

  • socket <Socket>

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

// main namespace
io.on("connection", (socket) => {
  // ...
});

// custom namespace
io.of("/admin").on("connection", (socket) => {
  // ...
});

Событие: 'connect'

Синоним события Event: "connection".

Флаг: 'volatile'

Устанавливает модификатор для последующей эмиссии события, что данные события могут быть потеряны, если клиенты не готовы получать сообщения (из-за медленной работы сети или других проблем, или потому что они подключены через длинный опрос и находятся в середине цикла запроса-ответа).

io.volatile.emit("an event", { some: "data" }); // the clients may or may not receive it

Флаг: 'local'

Устанавливает модификатор для последующей эмиссии события, что данные события будут только рассылаться текущему узлу (при масштабировании до нескольких узлов).

io.local.emit("an event", { some: "data" });

Сокет

Socket in the class diagram for the server

Класс Socket является основным классом для взаимодействия с клиентами браузера. Класс Socket принадлежит определённому Namespace (по умолчанию /) и использует подлежащий Client для связи.

Следует отметить, что Socket не относится напрямую к фактическому подлежащему TCP/IP socket и является только названием класса.

Внутри каждого Namespace, вы также можете определить произвольные каналы (называемые room), к которым Socket может присоединяться и отсоединяться. Это предоставляет удобный способ отправки сообщений группе Socket (см. Socket#to ниже).

Класс Socket наследуется от EventEmitter. Класс Socket переопределяет метод emit, и не изменяет другие методы EventEmitter. Все описанные здесь методы, которые также появляются как методы EventEmitter (кроме emit) реализованы классом EventEmitter, и документация для EventEmitter применима.

Дополнительную информацию можно найти здесь.

socket.id

  • <string>

Уникальный идентификатор сеанса, полученный от подлежащего Client.

socket.rooms

  • Set<string>

Множество строк, идентифицирующих комнаты, в которых находится этот клиент.

io.on("connection", (socket) => {

  console.log(socket.rooms); // Set { <socket.id> }

  socket.join("room1");

  console.log(socket.rooms); // Set { <socket.id>, "room1" }

});

socket.client

  • <Client>

Ссылка на подлежащий объект Client.

socket.conn

  • <engine.Socket>

Ссылка на подключение транспортного уровня Client (объект engine.io Socket). Это позволяет получить доступ к транспортному слою ввода-вывода, который всё ещё (в основном) абстрагирует фактический сокет TCP/IP.

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.request

  • <http.IncomingMessage>

Прокси-метод-геттер, который возвращает ссылку на request , который инициировал подлежащий транспорт engine.io Client. Полезно для доступа к заголовкам запроса, таким как Cookie или User-Agent.

import { parse } from "cookie";

io.on("connection", (socket) => {
  const cookies = parse(socket.request.headers.cookie || "");
});

socket.handshake

  • <Object>

Подробности рукопожатия:

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

Использование:

io.use((socket, next) => {
  let handshake = socket.handshake;
  // ...
});

io.on("connection", (socket) => {
  let handshake = socket.handshake;
  // ...
});

socket.data

Добавлена в v4.0.0

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

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

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

Это также работает в кластере Socket.IO с совместимым адаптером, например, адаптером Postgres.

socket.use(fn)

История
Версия Изменения
v3.0.5 Восстановление первой реализации.
v3.0.0 Удаление в пользу socket.onAny().
v1.7.2 Событие error отправляется непосредственно клиенту.
v1.6.0 Первая реализация.
  • fn <Function>

Регистрирует middleware, который является функцией, выполняемой для каждого входящего Packet и получает в качестве параметра пакет и функцию для опциональной отсрочки выполнения до следующего зарегистрированного middleware.

Ошибки, переданные обратной функции middleware, затем передаются как события error на стороне сервера:

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

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

socket.send([...args][, ack])

  • args <any[]>
  • ack <Function>
  • Возвращает Socket

Отправляет событие message. См. socket.emit(eventName[, ...args][, ack]).

socket.emit(eventName[, ...args][, ack])

(переопределяет EventEmitter.emit)

  • eventName <string> | <symbol>
  • args <any[]>
  • ack <Function>
  • Возвращает true

Выпускает событие для сокета, идентифицированного строковым именем. Можно включить любые другие параметры. Поддерживаются все сериализуемые структуры данных, включая Buffer.

socket.emit("hello", "world");
socket.emit("with-binary", 1, "2", { 3: "4", 5: Buffer.from([6]) });

Аргумент ack необязателен и будет вызван с ответом клиента.

Сервер

io.on("connection", (socket) => {
  socket.emit("hello", "world", (response) => {
    console.log(response); // "got it"
  });
});

Клиент

socket.on("hello", (arg, callback) => {
  console.log(arg); // "world"
  callback("got it");
});

socket.on(eventName, callback)

Унаследовано от класса EventEmitter.

  • eventName <string> | <symbol>
  • callback <Function>
  • Возвращает <Socket>

Регистрирует новый обработчик для данного события.

socket.on("news", (data) => {
  console.log(data);
});
// with several arguments
socket.on("news", (arg1, arg2, arg3) => {
  // ...
});
// or with acknowledgement
socket.on("news", (data, callback) => {
  callback(0);
});

socket.once(eventName, listener)

socket.removeListener(eventName, listener)

socket.removeAllListeners([eventName])

socket.eventNames()

Унаследовано от EventEmitter (вместе с другими методами, не упомянутыми здесь). См. документацию Node.js для модуля events.

socket.onAny(callback)

  • callback <Function>

Регистрирует новый обработчик "catch-all".

socket.onAny((event, ...args) => {
  console.log(`got ${event}`);
});

socket.prependAny(callback)

  • callback <Function>

Регистрирует новый обработчик "catch-all". Обработчик добавляется в начало массива обработчиков.

socket.prependAny((event, ...args) => {
  console.log(`got ${event}`);
});

socket.offAny([listener])

  • listener <Function>

Удаляет ранее зарегистрированный обработчик. Если обработчик не указан, удаляются все обработчики "catch-all".

const myListener = () => { /* ... */ };

socket.onAny(myListener);

// then, later
socket.offAny(myListener);

socket.offAny();

socket.listenersAny()

  • Возвращает <Function[]>

Возвращает список зарегистрированных обработчиков "catch-all".

const listeners = socket.listenersAny();

socket.onAnyOutgoing(callback)

Добавлена в v4.5.0

  • callback <Function>

Регистрирует новый обработчик "catch-all" для исходящих пакетов.

socket.onAnyOutgoing((event, ...args) => {
  console.log(`got ${event}`);
});

socket.prependAnyOutgoing(callback)

Добавлена в v4.5.0

  • callback <Function>

Регистрирует новый обработчик "catch-all" для исходящих пакетов. Обработчик добавляется в начало массива обработчиков.

socket.prependAnyOutgoing((event, ...args) => {
  console.log(`got ${event}`);
});

socket.offAnyOutgoing([listener])

Добавлена в v4.5.0

  • listener <Function>

Удаляет ранее зарегистрированный обработчик. Если обработчик не указан, удаляются все обработчики "catch-all".

const myListener = () => { /* ... */ };

socket.onAnyOutgoing(myListener);

// remove a single listener
socket.offAnyOutgoing(myListener);

// remove all listeners
socket.offAnyOutgoing();

socket.listenersAnyOutgoing()

Добавлена в v4.5.0

  • Возвращает <Function[]>

Возвращает список зарегистрированных слушателей всех исходящих пакетов.

const listeners = socket.listenersAnyOutgoing();

socket.join(room)

  • room <string> | <string[]>
  • Возвращает void | Promise

Добавляет сокет в указанную room или в список комнат.

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

  socket.join(["room 237", "room 238"]);

  io.to("room 237").emit("a new user has joined the room"); // broadcast to everyone in the room
});

Механизм присоединения к комнатам обрабатывается настроенным Adapter (см. Server#adapter выше), по умолчанию используя socket.io-adapter.

Для удобства каждый сокет автоматически присоединяется к комнате, идентифицируемой по его ID (см. Socket#id). Это упрощает рассылку сообщений другим сокетам:

io.on("connection", (socket) => {
  socket.on("say to someone", (id, msg) => {
    // send a private message to the socket with the given id
    socket.to(id).emit("my message", msg);
  });
});

socket.leave(room)

  • room <string>
  • Возвращает void | Promise

Удаляет сокет из указанной room.

io.on("connection", (socket) => {
  socket.leave("room 237");

  io.to("room 237").emit(`user ${socket.id} has left the room`);
});

Комнаты покидаются автоматически при отключении.

socket.to(room)

История
Версия Изменения
v4.0.0 Разрешает передавать массив комнат.
v1.0.0 Первая реализация.
  • room <string> | <string[]>
  • Возвращает Socket для цепочки вызовов

Устанавливает модификатор для последующей отправки события, при котором событие будет только рассылано клиентам, подключенным к заданной room (сам сокет исключается).

Для отправки в несколько комнат, вы можете вызвать to несколько раз.

io.on("connection", (socket) => {

  // to one room
  socket.to("others").emit("an event", { some: "data" });

  // to multiple rooms
  socket.to("room1").to("room2").emit("hello");

  // or with an array
  socket.to(["room1", "room2"]).emit("hello");

  // a private message to another socket
  socket.to(/* another socket id */).emit("hey");

  // WARNING: `socket.to(socket.id).emit()` will NOT work, as it will send to everyone in the room
  // named `socket.id` but the sender. Please use the classic `socket.emit()` instead.
});

Примечание: подтверждения не поддерживаются при рассылке.

socket.in(room)

Добавлена в v1.0.0

Синоним для socket.to(room).

socket.except(rooms)

Добавлена в v4.0.0

  • rooms <string> | <string[]>
  • Возвращает BroadcastOperator

Устанавливает модификатор для последующей отправки события, при котором событие будет только рассылано клиентам, которые не подключены к указанным rooms (сам сокет исключается).

// to all clients except the ones in "room1" and the sender
socket.broadcast.except("room1").emit(/* ... */);

// same as above
socket.except("room1").emit(/* ... */);

// to all clients in "room4" except the ones in "room5" and the sender
socket.to("room4").except("room5").emit(/* ... */);

socket.compress(value)

  • value <boolean> нужно ли сжимать следующий пакет
  • Возвращает Socket для цепочки вызовов

Устанавливает модификатор для последующей отправки события, что данные события будут сжаты, только если значение равно true. По умолчанию true если метод не вызывается.

io.on("connection", (socket) => {
  socket.compress(false).emit("uncompressed", "that's rough");
});

socket.timeout(value)

Добавлена в v4.4.0

  • value <number>
  • Возвращает <Socket>

Устанавливает модификатор для последующей отправки события, что коллбэк будет вызван с ошибкой, если заданное количество миллисекунд прошло без подтверждения от клиента:

socket.timeout(5000).emit("my-event", (err) => {
  if (err) {
    // the client did not acknowledge the event in the given delay
  }
});

socket.disconnect(close)

  • close <boolean> нужно ли закрыть базовое соединение
  • Возвращает Socket

Отключает этот сокет. Если значение close равно true, закрывает базовое соединение. В противном случае просто отключает пространство имен.

io.on("connection", (socket) => {
  setTimeout(() => socket.disconnect(true), 5000);
});

Флаг: 'broadcast'

Устанавливает модификатор для последующей отправки события, что данные события будут только рассыланы всем сокетам, кроме отправителя.

io.on("connection", (socket) => {
  socket.broadcast.emit("an event", { some: "data" }); // everyone gets it but the sender
});

Флаг: 'volatile'

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

io.on("connection", (socket) => {
  socket.volatile.emit("an event", { some: "data" }); // the client may or may not receive it
});

Событие: 'disconnect'

  • reason <string> причина отключения (клиентская или серверная)

Вызывается при отключении.

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 Соединение было закрыто (например, пользователь потерял соединение или сеть была изменена с Wi-Fi на 4G).
transport error Соединение столкнулось с ошибкой.
parse error Сервер получил неверный пакет от клиента.
forced close Сервер получил неверный пакет от клиента.
forced server close Клиент не присоединился к пространству имен вовремя (см. опцию connectTimeout) и был насильно закрыт.

Событие: 'disconnecting'

  • reason <string> причина отключения (клиентская или серверная)

Вызывается, когда клиент собирается отключиться (но еще не покинул свое rooms).

io.on("connection", (socket) => {
  socket.on("disconnecting", (reason) => {
    console.log(socket.rooms); // Set { ... }
  });
});

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

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

Клиент

Client in the class diagram for the server

Класс Client представляет входящее транспортное (engine.io) соединение. Один Client может быть связан со многими множественно-доступными Socket , которые принадлежат различным Namespace.

client.conn

  • <engine.Socket>

Ссылка на базовое engine.io Socket соединение.

client.request

  • <http.IncomingMessage>

Прокси-получатель, который возвращает ссылку на request , который инициировал соединение engine.io. Полезно для доступа к заголовкам запроса, таким как Cookie или User-Agent.

Движок

Сервер Engine.IO, который управляет соединениями WebSocket / HTTP длительного опрашивания. Дополнительная информация здесь.

Его исходный код можно найти здесь: https://github.com/socketio/engine.io

engine.clientsCount

Добавлена в v1.0.0

  • <number>

Количество подключенных клиентов.

const count = io.engine.clientsCount;
// may or may not be similar to the count of Socket instances in the main namespace, depending on your usage
const count2 = io.of("/").sockets.size;

engine.generateId

  • <Function>

Функция, используемая для генерации нового идентификатора сеанса. По умолчанию base64id.

const uuid = require("uuid");

io.engine.generateId = () => {
  return uuid.v4(); // must be unique across all Socket.IO servers
}

engine.handleUpgrade(request, socket, head)

Добавлена в v1.0.0

  • request <http.IncomingMessage> входящий запрос
  • socket <stream.Duplex> сокет сети между сервером и клиентом
  • head <Buffer> первый пакет обновленного потока (может быть пустым)

Этот метод может быть использован для вставки обновления HTTP:

Пример с сервером Socket.IO и обычным сервером WebSocket:

import { createServer } from "http";
import { Server as WsServer } from "ws";
import { Server } from "socket.io";

const httpServer = createServer();
const wss = new WsServer({ noServer: true });
const io = new Server(httpServer);

httpServer.removeAllListeners("upgrade");

httpServer.on("upgrade", (req, socket, head) => {
  if (req.url === "/") {
    wss.handleUpgrade(req, socket, head, (ws) => {
      wss.emit("connection", ws, req);
    });
  } else if (req.url.startsWith("/socket.io/")) {
    io.engine.handleUpgrade(req, socket, head);
  } else {
    socket.destroy();
  }
});

httpServer.listen(3000);

Событие: 'initial_headers'

Добавлен в v4.1.0

  • headers <Object> хеш заголовков, индексированных по имени заголовка
  • request <http.IncomingMessage> входящий запрос

Это событие будет испускаться незадолго до записи заголовков ответа первого HTTP запроса сессии (рукопожатия), позволяя вам настроить их.

import { serialize } from "cookie";

io.engine.on("initial_headers", (headers, request) => {
  headers["set-cookie"] = serialize("uid", "1234", { sameSite: "strict" });
});

Если вам нужно выполнить некоторые асинхронные операции, вам нужно использовать опцию allowRequest:

import { serialize } from "cookie";

const io = new Server(httpServer, {
  allowRequest: async (req, callback) => {
    const session = await fetchSession(req);
    req.session = session;
    callback(null, true);
  }
});

io.engine.on("initial_headers", (headers, req) => {
  if (req.session) {
    headers["set-cookie"] = serialize("sid", req.session.id, { sameSite: "strict" });
  }
});

См. также:

  • как использовать с express-session
  • как работать с куки

Событие: 'headers'

Добавлен в v4.1.0

  • headers <Object> хеш заголовков, индексированных по имени заголовка
  • request <http.IncomingMessage> входящий запрос

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

import { serialize, parse } from "cookie";

io.engine.on("headers", (headers, request) => {
  if (!request.headers.cookie) return;
  const cookies = parse(request.headers.cookie);
  if (!cookies.randomId) {
    headers["set-cookie"] = serialize("randomId", "abc", { maxAge: 86400 });
  }
});

Событие: 'connection_error'

Добавлен в v4.1.0

  • error <Error>
io.engine.on("connection_error", (err) => {
  console.log(err.req);      // the request object
  console.log(err.code);     // the error code, for example 1
  console.log(err.message);  // the error message, for example "Session ID unknown"
  console.log(err.context);  // some additional error context
});

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

Код Сообщение
0 "Тип транспорта неизвестен"
1 "Идентификатор сессии неизвестен"
2 "Неверный метод рукопожатия"
3 "Неверный запрос"
4 "Запрещено"
5 "Неподдерживаемая версия протокола"

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

Spec-Zone.ru

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