跳至主要内容
版本:4.x

服务器实例

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

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

Server#engine

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

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

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;

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

const uuid = require("uuid");

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

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

  • initial_headers:将在写入会话第一个 HTTP 请求(握手)的响应头之前发出,允许您自定义它们。
io.engine.on("initial_headers", (headers, req) => {
headers["test"] = "123";
headers["set-cookie"] = "mycookie=456";
});
  • headers:将在写入会话每个 HTTP 请求(包括 WebSocket 升级)的响应头之前发出,允许您自定义它们。
io.engine.on("headers", (headers, req) => {
headers["test"] = "789";
});
  • connection_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"会话 ID 未知"
2"错误的握手方法"
3"错误的请求"
4"禁止"
5"不支持的协议版本"

实用程序方法

Socket.IO v4.0.0 中添加了一些实用程序方法来管理套接字实例及其房间

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

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

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

这使得 "admin" 命名空间的所有套接字实例

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

断开连接。

请注意,它们也与 Redis 适配器兼容(从 socket.io-redis@6.1.0 开始),这意味着它们将在 Socket.IO 服务器之间工作。

socketsJoin

此方法使匹配的套接字实例加入指定的房间

// 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");

socketsLeave

此方法使匹配的套接字实例离开指定的房间

// 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");

disconnectSockets

此方法使匹配的套接字实例断开连接

// 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();

fetchSockets

此方法返回匹配的套接字实例

// 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();

// 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"

serverSideEmit

此方法允许将事件发射到集群中的其他 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");
});

注意

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

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

示例

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
}
});

事件

服务器实例发出一个事件(实际上是两个,但 connectconnection 的别名)

connection

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

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

完整 API

服务器实例公开的完整 API 可以在这里找到 这里