服务器实例
服务器实例(在代码示例中通常称为 io
)具有一些可能在你的应用中使用的属性。
¥The Server instance (often called io
in the code examples) has a few attributes that may be of use in your application.
它还继承了 主命名空间 的所有方法,例如 namespace.use()
(参见 此处)或 namespace.allSockets()
。
¥It also inherits all the methods of the main namespace, like namespace.use()
(see here) or namespace.allSockets()
.
Server#engine
对底层 Engine.IO 服务器的引用。
¥A reference to the underlying Engine.IO server.
它可用于获取当前连接的客户端数量:
¥It can be used to fetch the number of currently connected clients:
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
查询参数):
¥Or to generate a custom session ID (the sid
query parameter):
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 服务器触发三个特殊事件:
¥As of socket.io@4.1.0
, the Engine.IO server emits three special events:
initial_headers
:将在写入会话的第一个 HTTP 请求(握手)的响应标头之前触发,允许你自定义它们。¥
initial_headers
: will be emitted just before writing the response headers of the first HTTP request of the session (the handshake), allowing you to customize them.
io.engine.on("initial_headers", (headers, req) => {
headers["test"] = "123";
headers["set-cookie"] = "mycookie=456";
});
headers
:将在写入会话的每个 HTTP 请求的响应标头(包括 WebSocket 升级)之前触发,允许你自定义它们。¥
headers
: will be emitted just before writing the response headers of each HTTP request of the session (including the WebSocket upgrade), allowing you to customize them.
io.engine.on("headers", (headers, req) => {
headers["test"] = "789";
});
connection_error
:当连接异常关闭时会触发¥
connection_error
: will be emitted when a connection is abnormally closed
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
});
以下是可能的错误代码列表:
¥Here is the list of possible error codes:
代码 | 消息 |
---|---|
0 | "运输未知" |
1 | "会话 ID 未知" |
2 | "错误的握手方式" |
3 | "错误的请求" |
4 | "禁止" |
5 | "不支持的协议版本" |
实用方法
¥Utility methods
Socket.IO v4.0.0 中添加了一些实用方法来管理 Socket 实例及其房间:
¥Some utility methods were added in Socket.IO v4.0.0 to manage the Socket instances and their rooms:
socketsJoin
:使匹配的套接字实例加入指定的房间¥
socketsJoin
: makes the matching socket instances join the specified roomssocketsLeave
:使匹配的套接字实例离开指定的房间¥
socketsLeave
: makes the matching socket instances leave the specified roomsdisconnectSockets
:使匹配的套接字实例断开连接¥
disconnectSockets
: makes the matching socket instances disconnectfetchSockets
:返回匹配的套接字实例¥
fetchSockets
: returns the matching socket instances
serverSideEmit
方法是在 Socket.IO v4.1.0 中添加的。
¥The serverSideEmit
method was added in Socket.IO v4.1.0.
这些方法与广播具有相同的语义,并且应用相同的过滤器:
¥Those methods share the same semantics as broadcasting, and the same filters apply:
io.of("/admin").in("room1").except("room2").local.disconnectSockets();
这使得 "管理" 命名空间的所有 Socket 实例
¥Which makes all Socket instances of the "admin" namespace
在 "room1" 房间(
in("room1")
或to("room1")
)¥in the "room1" room (
in("room1")
orto("room1")
)除 "room2"(
except("room2")
)中的¥except the ones in "room2" (
except("room2")
)并且仅在当前 Socket.IO 服务器 (
local
) 上¥and only on the current Socket.IO server (
local
)
断开。
¥disconnect.
请注意,它们还与 Redis 适配器兼容(从 socket.io-redis@6.1.0
开始),这意味着它们可以跨 Socket.IO 服务器工作。
¥Please note that they are also compatible with the Redis adapter (starting with socket.io-redis@6.1.0
), which means that they will work across Socket.IO servers.
socketsJoin
此方法使匹配的 Socket 实例加入指定的房间:
¥This method makes the matching Socket instances join the specified 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"]);
// 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
该方法使匹配的 Socket 实例离开指定的房间:
¥This method makes the matching Socket instances leave the specified 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"]);
// 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
此方法使匹配的 Socket 实例断开连接:
¥This method makes the matching Socket instances disconnect:
// 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
此方法返回匹配的 Socket 实例:
¥This method returns the matching Socket instances:
// 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 类的子集:
¥The sockets
variable in the example above is an array of objects exposing a subset of the usual Socket class:
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 服务器之间共享信息:
¥The data
attribute is an arbitrary object that can be used to share information between Socket.IO servers:
// 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 服务器(在 多服务器设置 中)。
¥This method allows to emit events to the other Socket.IO servers of the cluster, in a multi-server setup.
语法:
¥Syntax:
io.serverSideEmit("hello", "world");
在接收端:
¥And on the receiving side:
io.on("hello", (arg1) => {
console.log(arg1); // prints "world"
});
也支持回执:
¥Acknowledgements are supported too:
// server A
io.serverSideEmit("ping", (err, responses) => {
console.log(responses[0]); // prints "pong"
});
// server B
io.on("ping", (cb) => {
cb("pong");
});
注意:
¥Notes:
connection
、connect
和new_namespace
字符串是保留的,不能在你的应用中使用。¥the
connection
,connect
andnew_namespace
strings are reserved and cannot be used in your application.你可以发送任意数量的参数,但当前不支持二进制结构(参数数组将是
JSON.stringify
-ed)¥you can send any number of arguments, but binary structures are currently not supported (the array of arguments will be
JSON.stringify
-ed)
示例:
¥Example:
io.serverSideEmit("hello", "world", 1, "2", { 3: "4" });
如果其他 Socket.IO 服务器在给定的延迟后没有响应,则调用确认回调可能会出现错误
¥the acknowledgement callback might be called with an error, if the other Socket.IO servers do not respond after a given delay
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
}
});
事件
¥Events
服务器实例触发一个事件(从技术上讲,是两个事件,但 connect
是 connection
的别名):
¥The Server instance emits one single event (well, technically two, but connect
is an alias for connection
):
connection
该事件在新连接时触发。第一个参数是 套接字实例。
¥This event is fired upon a new connection. The first argument is a Socket instance.
io.on("connection", (socket) => {
// ...
});
完整的 API
¥Complete API
Server 实例暴露的完整 API 可以参见 此处。
¥The complete API exposed by the Server instance can be found here.