服务器实例

服务器实例(通常io在代码示例中调用)具有一些可能在您的应用程序中使用的属性。

它还继承了主命名空间的所有方法,例如namespace.use()(参见此处)或 namespace.allSockets().

服务器#engine

对底层 Engine.IO 服务器的引用。

它可用于获取当前连接的客户端数量:

  1. const count = io.engine.clientsCount;
  2. // 根据您的用法,可能与主命名空间中的Socket实例计数相似或不相似
  3. const count2 = io.of("/").sockets.size;

或者生成自定义会话 ID(sid查询参数):

  1. const uuid = require("uuid");
  2. io.engine.generateId = (req) => {
  3. return uuid.v4(); // 必须在所有socket.io服务器上都是唯一的
  4. }

socket.io@4.1.0开始,Engine.IO 服务器发出三个特殊事件:

  • initial_headers: 将在编写会话的第一个 HTTP 请求(握手)的响应标头之前发出,允许您自定义它们。
  1. io.engine.on("initial_headers", (headers, req) => {
  2. headers["test"] = "123";
  3. headers["set-cookie"] = "mycookie=456";
  4. });
  • headers: 将在编写会话的每个 HTTP 请求的响应头之前发出(包括 WebSocket 升级),允许您自定义它们。
  1. io.engine.on("headers", (headers, req) => {
  2. headers["test"] = "789";
  3. });
  • connection_error: 当连接异常关闭时发出
  1. io.engine.on("connection_error", (err) => {
  2. console.log(err.req); // the request object
  3. console.log(err.code); // the error code, for example 1
  4. console.log(err.message); // the error message, for example "Session ID unknown"
  5. console.log(err.context); // some additional error context
  6. });

以下是可能的错误代码列表:

CodeMessage
0“Transport unknown”
1“Session ID unknown”
2“Bad handshake method”
3“Bad request”
4“Forbidden”
5“Unsupported protocol version”

实用方法

Socket.IO v4.0.0 中添加了一些实用方法来管理 Socket 实例及其房间:

serverSideEmit方法是在 Socket.IO v4.1.0 中添加的。

这些方法与广播共享相同的语义,并且应用相同的过滤器:

  1. io.of("/admin").in("room1").except("room2").local.disconnectSockets();

这使得“admin”命名空间的所有 Socket 实例

  • 在“room1”房间 (in("room1") or to("room1"))
  • 除了 “room2” (except("room2"))
  • 并且仅在当前的 Socket.IO 服务器上 (local)

断开。

请注意,它们还与 Redis 适配器兼容(以socket.io-redis@6.1.0开头),这意味着它们可以跨 Socket.IO 服务器工作。

socketsJoin

此方法使匹配的 Socket 实例加入指定的房间:

  1. // make all Socket instances join the "room1" room
  2. io.socketsJoin("room1");
  3. // make all Socket instances in the "room1" room join the "room2" and "room3" rooms
  4. io.in("room1").socketsJoin(["room2", "room3"]);
  5. // make all Socket instances in the "room1" room of the "admin" namespace join the "room2" room
  6. io.of("/admin").in("room1").socketsJoin("room2");
  7. // this also works with a single socket ID
  8. io.in(theSocketId).socketsJoin("room1");

socketsLeave

该方法使匹配的 Socket 实例离开指定房间:

  1. // make all Socket instances leave the "room1" room
  2. io.socketsLeave("room1");
  3. // make all Socket instances in the "room1" room leave the "room2" and "room3" rooms
  4. io.in("room1").socketsLeave(["room2", "room3"]);
  5. // make all Socket instances in the "room1" room of the "admin" namespace leave the "room2" room
  6. io.of("/admin").in("room1").socketsLeave("room2");
  7. // this also works with a single socket ID
  8. io.in(theSocketId).socketsLeave("room1");

disconnectSockets

此方法使匹配的 Socket 实例断开连接:

  1. // make all Socket instances disconnect
  2. io.disconnectSockets();
  3. // make all Socket instances in the "room1" room disconnect (and discard the low-level connection)
  4. io.in("room1").disconnectSockets(true);
  5. // make all Socket instances in the "room1" room of the "admin" namespace disconnect
  6. io.of("/admin").in("room1").disconnectSockets();
  7. // this also works with a single socket ID
  8. io.of("/admin").in(theSocketId).disconnectSockets();

fetchSockets

此方法返回匹配的 Socket 实例:

  1. // return all Socket instances of the main namespace
  2. const sockets = await io.fetchSockets();
  3. // return all Socket instances in the "room1" room of the main namespace
  4. const sockets = await io.in("room1").fetchSockets();
  5. // return all Socket instances in the "room1" room of the "admin" namespace
  6. const sockets = await io.of("/admin").in("room1").fetchSockets();
  7. // this also works with a single socket ID
  8. const sockets = await io.in(theSocketId).fetchSockets();

上例中的sockets变量是一个对象数组,暴露了通常的 Socket 类的一个子集:

  1. for (const socket of sockets) {
  2. console.log(socket.id);
  3. console.log(socket.handshake);
  4. console.log(socket.rooms);
  5. console.log(socket.data);
  6. socket.emit(/* ... */);
  7. socket.join(/* ... */);
  8. socket.leave(/* ... */);
  9. socket.disconnect(/* ... */);
  10. }

data属性是一个任意对象,可用于在 Socket.IO 服务器之间共享信息:

  1. // server A
  2. io.on("connection", (socket) => {
  3. socket.data.username = "alice";
  4. });
  5. // server B
  6. const sockets = await io.fetchSockets();
  7. console.log(sockets[0].data.username); // "alice"

serverSideEmit

此方法允许在多服务器设置中向集群的其他 Socket.IO 服务器发出事件。

语法:

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

在接收方:

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

也支持确认:

  1. // server A
  2. io.serverSideEmit("ping", (err, responses) => {
  3. console.log(responses[0]); // prints "pong"
  4. });
  5. // server B
  6. io.on("ping", (cb) => {
  7. cb("pong");
  8. });

笔记:

  • connectionconnectnew_namespace 字符串是保留的,不能在您的应用程序中使用。

  • 您可以发送任意数量的参数,但目前不支持二进制结构(参数数组将被JSON.stringify-ed)

例子:

  1. io.serverSideEmit("hello", "world", 1, "2", { 3: "4" });
  • 如果其他 Socket.IO 服务器在给定延迟后没有响应,则调用确认回调可能会出错
  1. io.serverSideEmit("ping", (err, responses) => {
  2. if (err) {
  3. // at least one Socket.IO server has not responded
  4. // the 'responses' array contains all the responses already received though
  5. } else {
  6. // success! the 'responses' array contains one object per other Socket.IO server in the cluster
  7. }
  8. });

Events

Server 实例发出一个事件(好吧,从技术上讲是两个,但connect它是connection的别名):

connection

此事件在新连接时触发。第一个参数是一个Socket实例.

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

完整API

可以在此处找到服务器实例公开的完整 API 。