服务器 API
服务器


相关文档页面
构造函数
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])
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);
可以在 这里 找到所有可用选项的完整列表。
事件
事件: 'connect'
是 事件: "connection" 的同义词。
事件: 'connection'
socket
(Socket) 与客户端的套接字连接
在客户端连接时触发。
io.on("connection", (socket) => {
// ...
});
事件: '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);
});
属性
server.engine
对底层 Engine.IO 服务器的引用。见 这里。
server.sockets
主命名空间 (/
) 的别名。
io.sockets.emit("hi", "everyone");
// is equivalent to
io.of("/").emit("hi", "everyone");
方法
server.adapter([value])
设置适配器 value
。默认为 socket.io 附带的 Adapter
实例,它是基于内存的。见 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>
使用提供的 options
将 Server
附加到 httpServer
。
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])
使用提供的 options
在给定的 port
上附加 Server
。
import { Server } from "socket.io";
const io = new Server();
io.attach(3000);
io.on("connection", (socket) => {
// ...
});
server.attachApp(app[, options])
将 Socket.IO 服务器附加到 µWebSockets.js 应用程序
import { App } from "uWebSockets.js";
import { Server } from "socket.io";
const app = 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.bind(engine)
engine
<engine.Server>
- 返回
<Server>
仅供高级使用。将服务器绑定到特定的 engine.io Server
(或兼容 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.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 连接的客户端不会立即断开连接。
server.disconnectSockets([close])
在 v4.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);
此方法也适用于多个 Socket.IO 服务器的集群,并使用兼容的适配器,例如 Postgres 适配器。
在这种情况下,如果您只想影响给定节点上的套接字实例,则需要使用 local
标志
// make all Socket instances that are currently connected on the given node disconnect
io.local.disconnectSockets();
见 这里。
server.emit(eventName[, ...args])
历史
版本 | 更改 |
---|---|
v4.5.0 | io.emit() 现在支持确认。 |
v1.0.0 | 初始实现。 |
向主命名空间中的所有连接的客户端发出事件。
io.emit("hello");
可以包含任意数量的参数,并且支持所有可序列化数据结构
io.emit("hello", 1, "2", { "3": 4 }, Buffer.from([5]));
在接收方
socket.on("hello", (arg1, arg2, arg3, arg4) => {
console.log(arg1); // 1
console.log(arg2); // "2"
console.log(arg3); // { "3": 4 }
console.log(arg4); // ArrayBuffer or Buffer, depending on the platform
});
参数将自动序列化,因此不需要调用 JSON.stringify()
。
您可以使用 to()
和 except()
将数据包发送到特定客户端
// the “hello” event will be broadcast to all connected clients that are either
// in the "room1" room or in the "room2" room, excluding those in the "room3" room
io.to("room1").to("room2").except("room3").emit("hello");
从版本 4.5.0
开始,现在可以在广播时使用确认
io.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
}
});
在这种情况下,必须调用 timeout()
。
server.emitWithAck(eventName[, ...args])
在 v4.6.0 中添加
eventName
<string>
|<symbol>
args
any[]
- 返回
Promise<any[]>
基于 Promise 的广播版本,并期望从所有目标客户端收到确认
try {
const responses = await io.timeout(10000).emitWithAck("some-event");
console.log(responses); // one response per client
} catch (e) {
// some clients did not acknowledge the event in the given delay
}
上面的示例等效于
io.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
}
});
在接收方
socket.on("some-event", (callback) => {
callback("got it"); // only one argument is expected
});
server.except(rooms)
在 v4.0.0 中添加
rooms
<string>
|<string[]>
- 返回
BroadcastOperator
为后续事件发射设置一个修饰符,该事件将仅广播到未加入给定 rooms
的客户端。
// the "foo" event will be broadcast to all connected clients, except the ones that are in the "room-101" room
io.except("room-101").emit("foo", "bar");
// with an array of rooms
io.except(["room-101", "room-102"]).emit("foo", "bar");
// with multiple chained calls
io.except("room-101").except("room-102").emit("foo", "bar");
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 (sockets.length === 0) {
// no more active connections for the given user
}
});
});
此方法也适用于多个 Socket.IO 服务器的集群,并使用兼容的适配器,例如 Postgres 适配器。
在这种情况下,如果您只想返回给定节点上的套接字实例,则需要使用 local
标志
// return all Socket instances that are currently connected on the given node
const sockets = await io.local.fetchSockets();
见 这里。
server.in(room)
在 v1.0.0 中添加
是 server.to(room) 的同义词,但在某些情况下可能更清晰
// disconnect all clients in the "room-101" room
io.in("room-101").disconnectSockets();
server.listen(httpServer[, options])
是 server.attach(httpServer[, options]) 的同义词。
server.listen(port[, options])
是 server.attach(port[, options]) 的同义词。
server.of(nsp)
nsp
<string>
|<RegExp>
|<Function>
- 返回值
<Namespace>
通过其路径名标识符 nsp
初始化并检索给定的 Namespace
。如果命名空间已初始化,则立即返回它。
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.on(eventName, listener)
继承自 EventEmitter 类。
eventName
<string>
|<symbol>
listener
<Function>
- 返回
<Server>
将 listener
函数添加到名为 eventName
的事件的监听器数组的末尾。
可用事件
connection
new_namespace
- 来自
serverSideEmit
方法的任何自定义事件
io.on("connection", (socket) => {
// ...
});
server.onconnection(socket)
socket
<engine.Socket>
- 返回
<Server>
仅供高级使用。从传入的 engine.io(或兼容 API)Socket
创建新的 socket.io
客户端。
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.path([value])
设置 engine.io
和静态文件将被提供的路径 value
。默认为 /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.serveClient([value])
如果 value
为 true
,则附加的服务器将提供客户端文件。默认为 true
。此方法在调用 listen
后无效。如果未提供任何参数,则此方法返回当前值。
import { Server } from "socket.io";
const io = new Server();
io.serveClient(false);
io.listen(3000);
server.serverSideEmit(eventName[, ...args][, ack])
在 v4.1.0 中添加
别名:io.of("/").serverSideEmit(/* ... */);
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
-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
}
});
server.serverSideEmitWithAck(eventName[, ...args])
在 v4.6.0 中添加
别名:io.of("/").serverSideEmitWithAck(/* ... */);
eventName
<string>
args
<any[]>
ack
<Function>
- 返回
Promise<any[]>
广播的基于 Promise 的版本,并期望来自 集群 的其他 Socket.IO 服务器的确认。
try {
const responses = await io.serverSideEmitWithAck("some-event");
console.log(responses); // one response per server (except itself)
} catch (e) {
// some servers did not acknowledge the event in the given delay
}
上面的示例等效于
io.serverSideEmit("some-event", (err, responses) => {
if (err) {
// some servers did not acknowledge the event in the given delay
} else {
console.log(responses); // one response per server (except itself)
}
});
在接收方
io.on("some-event", (callback) => {
callback("got it"); // only one argument is expected
});
server.socketsJoin(rooms)
在 v4.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");
此方法也适用于多个 Socket.IO 服务器的集群,并使用兼容的适配器,例如 Postgres 适配器。
在这种情况下,如果您只想影响给定节点上的套接字实例,则需要使用 local
标志
// make all Socket instances that are currently connected on the given node join the "room1" room
io.local.socketsJoin("room1");
见 这里。
server.socketsLeave(rooms)
在 v4.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");
此方法也适用于多个 Socket.IO 服务器的集群,并使用兼容的适配器,例如 Postgres 适配器。
在这种情况下,如果您只想影响给定节点上的套接字实例,则需要使用 local
标志
// make all Socket instances that are currently connected on the given node leave the "room1" room
io.local.socketsLeave("room1");
见 这里。
server.timeout(value)
在 v4.5.0 中添加
value
<number>
- 返回
BroadcastOperator
设置后续事件发射的修饰符,当给定的毫秒数过去而没有收到所有目标客户端的确认时,回调将被调用并出现错误
io.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
}
});
server.to(room)
历史
版本 | 更改 |
---|---|
v4.0.0 | 允许传递房间数组。 |
v1.0.0 | 初始实现。 |
room
<string>
|<string[]>
- 返回值 用于链接的
BroadcastOperator
设置后续事件发射的修饰符,该事件将仅广播给已加入给定 room
的客户端。
要向多个房间发射,您可以多次调用 to
。
// the “foo” event will be broadcast to all connected clients in the “room-101” room
io.to("room-101").emit("foo", "bar");
// with an array of rooms (a client will be notified at most once)
io.to(["room-101", "room-102"]).emit("foo", "bar");
// with multiple chained calls
io.to("room-101").to("room-102").emit("foo", "bar");
server.use(fn)
在 v1.0.0 中添加
fn
<Function>
为主命名空间注册中间件,该中间件是一个函数,它会为每个传入的 Socket
执行,并接收套接字和一个函数作为参数,该函数可以选择将执行延迟到下一个注册的中间件。
传递给中间件回调的错误将作为特殊的 connect_error
数据包发送给客户端。
服务器
io.use((socket, next) => {
const err = new Error("not authorized");
err.data = { content: "Please retry later" }; // additional details
next(err);
});
客户端
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" }
});
更多信息可以在 这里 找到。
如果您正在寻找 Express 中间件,请查看 本节。
命名空间


表示在给定范围内连接的套接字池,该范围由路径名标识(例如:/chat
)。
更多信息可以在 这里 找到。
属性
namespace.adapter
命名空间使用的 "适配器"。
注意: 主命名空间的适配器可以通过 io.of("/").adapter
访问。
更多关于它的信息 这里。
const adapter = io.of("/my-namespace").adapter;
namespace.name
命名空间标识符属性。
namespace.sockets
连接到此命名空间的 Socket 实例的映射。
// number of sockets in this namespace (on this node)
const socketCount = io.of("/admin").sockets.size;
事件
事件:'connect'
是 事件:"connection" 的同义词。
事件:'connection'
socket
<Socket>
在客户端连接时触发。
// main namespace
io.on("connection", (socket) => {
// ...
});
// custom namespace
io.of("/admin").on("connection", (socket) => {
// ...
});
方法
namespace.allSockets()
- 返回值
Promise<Set<SocketId>>
此方法将在下一个主要版本中删除,请改用 serverSideEmit()
或 fetchSockets()
。
获取连接到此命名空间的套接字 ID 列表(如果适用,跨所有节点)。
// 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.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.emit(eventName[, ...args])
历史
版本 | 更改 |
---|---|
v4.5.0 | io.emit() 现在支持确认。 |
v1.0.0 | 初始实现。 |
向给定命名空间中所有连接的客户端发射事件。
io.of("/chat").emit("hello");
可以包含任意数量的参数,并且支持所有可序列化数据结构
io.of("/chat").emit("hello", 1, "2", { "3": 4 }, Buffer.from([5]));
在接收方
socket.on("hello", (arg1, arg2, arg3, arg4) => {
console.log(arg1); // 1
console.log(arg2); // "2"
console.log(arg3); // { "3": 4 }
console.log(arg4); // ArrayBuffer or Buffer, depending on the platform
});
参数将自动序列化,因此不需要调用 JSON.stringify()
。
您可以使用 to()
和 except()
将数据包发送到特定客户端
// the “hello” event will be broadcast to all connected clients that are either
// in the "room1" room or in the "room2" room, excluding those in the "room3" room
io.of("/chat").to("room1").to("room2").except("room3").emit("hello");
从版本 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
}
});
在这种情况下,调用 timeout()
是强制性的。
namespace.emitWithAck(eventName[, ...args])
在 v4.6.0 中添加
eventName
<string>
|<symbol>
args
any[]
- 返回
Promise<any[]>
广播的基于 Promise 的版本,并期望来自给定命名空间中所有目标客户端的确认
try {
const responses = await io.of("/chat").timeout(10000).emitWithAck("some-event");
console.log(responses); // one response per client
} catch (e) {
// some clients did not acknowledge the event in the given delay
}
上面的示例等效于
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
}
});
在接收方
socket.on("some-event", (callback) => {
callback("got it"); // only one argument is expected
});
namespace.except(rooms)
在 v4.0.0 中添加
rooms
<string>
|<string[]>
- 返回
BroadcastOperator
为后续事件发射设置一个修饰符,该事件将仅广播到未加入给定 rooms
的客户端。
const myNamespace = io.of("/my-namespace");
// the "foo" event will be broadcast to all connected clients, except the ones that are in the "room-101" room
myNamespace.except("room-101").emit("foo", "bar");
// with an array of rooms
myNamespace.except(["room-101", "room-102"]).emit("foo", "bar");
// with multiple chained calls
myNamespace.except("room-101").except("room-102").emit("foo", "bar");
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.in(room)
在 v1.0.0 中添加
是 namespace.to(room) 的同义词,但在某些情况下可能感觉更清晰
const myNamespace = io.of("/my-namespace");
// disconnect all clients in the "room-101" room
myNamespace.in("room-101").disconnectSockets();
namespace.serverSideEmit(eventName[, ...args][, ack])
在 v4.1.0 中添加
eventName
<string>
args
<any[]>
ack
<Function>
- 返回
true
向 集群 的其他 Socket.IO 服务器发送消息。
语法
io.of("/chat").serverSideEmit("hello", "world");
在接收方
io.of("/chat").on("hello", (arg1) => {
console.log(arg1); // prints "world"
});
也支持确认
// server A
io.of("/chat").serverSideEmit("ping", (err, responses) => {
console.log(responses[0]); // prints "pong"
});
// server B
io.of("/chat").on("ping", (cb) => {
cb("pong");
});
注意
connection
、connect
和new_namespace
字符串是保留的,不能在您的应用程序中使用。您可以发送任意数量的参数,但目前不支持二进制结构(参数数组将被
JSON.stringify
-ed)
示例
io.of("/chat").serverSideEmit("hello", "world", 1, "2", { 3: "4" });
- 如果其他 Socket.IO 服务器在给定的延迟后没有响应,则确认回调可能会被调用并出现错误
io.of("/chat").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
}
});
namespace.serverSideEmitWithAck(eventName[, ...args])
在 v4.6.0 中添加
eventName
<string>
args
<any[]>
ack
<Function>
- 返回
Promise<any[]>
广播的基于 Promise 的版本,并期望来自 集群 的其他 Socket.IO 服务器的确认。
try {
const responses = await io.of("/chat").serverSideEmitWithAck("some-event");
console.log(responses); // one response per server (except itself)
} catch (e) {
// some servers did not acknowledge the event in the given delay
}
上面的示例等效于
io.of("/chat").serverSideEmit("some-event", (err, responses) => {
if (err) {
// some servers did not acknowledge the event in the given delay
} else {
console.log(responses); // one response per server (except itself)
}
});
在接收方
io.of("/chat").on("some-event", (callback) => {
callback("got it"); // only one argument is expected
});
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.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.to(room)
历史
版本 | 更改 |
---|---|
v4.0.0 | 允许传递房间数组。 |
v1.0.0 | 初始实现。 |
room
<string>
|<string[]>
- 返回值 用于链接的
BroadcastOperator
设置后续事件发射的修饰符,该事件将仅广播给已加入给定 room
的客户端。
要向多个房间发射,您可以多次调用 to
。
const myNamespace = io.of("/my-namespace");
// the “foo” event will be broadcast to all connected clients in the “room-101” room
myNamespace.to("room-101").emit("foo", "bar");
// with an array of rooms (a client will be notified at most once)
myNamespace.to(["room-101", "room-102"]).emit("foo", "bar");
// with multiple chained calls
myNamespace.to("room-101").to("room-102").emit("foo", "bar");
namespace.use(fn)
在 v1.0.0 中添加
fn
<Function>
为给定命名空间注册一个中间件,该中间件是一个函数,它会为每个传入的 Socket
执行,并接收套接字和一个可选的函数作为参数,以将执行延迟到下一个注册的中间件。
传递给中间件回调的错误将作为特殊的 connect_error
数据包发送给客户端。
服务器
io.of("/chat").use((socket, next) => {
const err = new Error("not authorized");
err.data = { content: "Please retry later" }; // additional details
next(err);
});
客户端
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" }
});
更多信息可以在 这里 找到。
如果您正在寻找 Express 中间件,请查看 本节。
标志
标志:'local'
为后续的事件发射设置一个修饰符,该修饰符将使事件数据仅广播到当前节点(当扩展到多个节点时)。
io.local.emit("an event", { some: "data" });
标志:'volatile'
为后续的事件发射设置一个修饰符,该修饰符将使事件数据可能丢失,如果客户端尚未准备好接收消息(由于网络缓慢或其他问题,或者因为它们通过长轮询连接并且处于请求-响应周期的中间)。
io.volatile.emit("an event", { some: "data" }); // the clients may or may not receive it
套接字


Socket
是与浏览器客户端交互的基本类。Socket
属于某个特定的 Namespace
(默认情况下为 /
),并使用底层的 Client
进行通信。
需要注意的是,Socket
与实际的底层 TCP/IP socket
没有直接关系,它只是类的名称。
在每个 Namespace
中,您还可以定义任意通道(称为 room
),Socket
可以加入和离开。这提供了一种方便的方式来广播到一组 Socket
(见下面的 Socket#to
)。
Socket
类继承自 EventEmitter。Socket
类覆盖了 emit
方法,并且没有修改任何其他 EventEmitter
方法。此处记录的所有方法(除了 emit
)也作为 EventEmitter
方法出现,这些方法都是由 EventEmitter
实现的,并且 EventEmitter
的文档适用。
更多信息可以在这里找到 here.
事件
事件:'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 | 客户端在 pingTimeout 延迟内没有发送 PONG 数据包。 |
transport close | 连接已关闭(例如:用户已断开连接,或网络已从 WiFi 更改为 4G)。 |
transport error | 连接遇到错误。 |
parse error | 服务器从客户端接收到了无效的数据包。 |
forced close | 服务器从客户端接收到了无效的数据包。 |
forced server close | 客户端没有及时加入命名空间(参见 connectTimeout 选项),并被强制关闭。 |
事件:'disconnecting'
在 v1.5.0 中添加
reason
<string>
断开连接的原因(客户端或服务器端)
当客户端即将断开连接时触发(但尚未离开其 rooms
)。
io.on("connection", (socket) => {
socket.on("disconnecting", (reason) => {
console.log(socket.rooms); // Set { ... }
});
});
使用异步处理程序,您需要创建 rooms
属性的副本
io.on("connection", (socket) => {
socket.on("disconnecting", async (reason) => {
const rooms = new Set(socket.rooms);
await someLongRunningOperation();
// socket.rooms will be empty there
console.log(rooms);
});
});
这些事件以及 connect
、connect_error
、newListener
和 removeListener
是特殊事件,不应在您的应用程序中使用
// BAD, will throw an error
socket.emit("disconnect");
属性
socket.client
对底层 Client
对象的引用。
socket.conn
<engine.Socket>
对底层 Client
传输连接(engine.io Socket
对象)的引用。这允许访问 IO 传输层,该层仍然(大部分)抽象了实际的 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.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.handshake
握手详细信息
字段 | 类型 | 描述 |
---|---|---|
headers | IncomingHttpHeaders | 作为握手的一部分发送的标头。 |
time | <string> | 创建日期(作为字符串)。 |
address | <string> | 客户端的 IP 地址。 |
xdomain | <boolean> | 连接是否跨域。 |
secure | <boolean> | 连接是否通过 SSL 建立。 |
issued | <number> | 创建日期(作为 Unix 时间戳)。 |
url | <string> | 请求 URL 字符串。 |
query | Record<string, string or string[]> | 第一个请求的查询参数。 |
auth | Record<string, any> | 身份验证有效负载。另见 here. |
用法
io.use((socket, next) => {
let handshake = socket.handshake;
// ...
});
io.on("connection", (socket) => {
let handshake = socket.handshake;
// ...
});
示例
const handshake = {
headers: {
"user-agent": "node-XMLHttpRequest",
accept: "*/*",
host: "localhost:3000",
connection: "close"
},
time: "Wed Jan 01 2020 01:00:00 GMT+0100 (Central European Standard Time)",
address: "::ffff:127.0.0.1",
xdomain: false,
secure: false,
issued: 1577836800000,
url: "/socket.io/?EIO=4&transport=polling&t=OPAfXv5&b64=1",
query: {
EIO: "4",
transport: "polling",
t: "OPAfXv5",
b64: "1"
},
auth: {}
}
注意:headers
属性指的是会话的第一个 HTTP 请求的标头,不会被后续的 HTTP 请求更新。
io.on("connection", (socket) => {
console.log(socket.handshake.headers === socket.request.headers); // prints "true"
});
socket.id
会话的唯一标识符,来自底层的 Client
。
id
属性是一个短暂的 ID,不应在您的应用程序中使用(或仅用于调试目的),因为
- 此 ID 在每次重新连接后都会重新生成(例如,当 WebSocket 连接断开时,或当用户刷新页面时)
- 两个不同的浏览器选项卡将具有两个不同的 ID
- 服务器上没有为给定 ID 存储消息队列(即,如果客户端断开连接,则从服务器发送到此 ID 的消息将丢失)
请使用常规会话 ID 代替(要么在 cookie 中发送,要么存储在 localStorage 中并在 auth
有效负载中发送)。
另见
socket.recovered
在 v4.6.0 中添加
在上次重新连接期间连接状态是否成功恢复。
io.on("connection", (socket) => {
if (socket.recovered) {
// recovery was successful: socket.id, socket.rooms and socket.data were restored
} else {
// new or unrecoverable session
}
});
有关此功能的更多信息,请参见 here.
socket.request
一个 getter 代理,它返回对产生底层 engine.io Client
的 request
的引用。对于访问请求标头(如 Cookie
或 User-Agent
)很有用。
import { parse } from "cookie";
io.on("connection", (socket) => {
const cookies = parse(socket.request.headers.cookie || "");
});
注意:socket.request
指的是会话的第一个 HTTP 请求,不会被后续的 HTTP 请求更新。
io.on("connection", (socket) => {
console.log(socket.request.headers === socket.handshake.headers); // prints "true"
});
如果您不需要此引用,可以将其丢弃以减少内存占用
io.on("connection", (socket) => {
delete socket.conn.request;
});
socket.rooms
一个字符串集,标识此客户端所在的房间。
io.on("connection", (socket) => {
console.log(socket.rooms); // Set { <socket.id> }
socket.join("room1");
console.log(socket.rooms); // Set { <socket.id>, "room1" }
});
方法
socket.compress(value)
value
<boolean>
是否压缩以下数据包- 返回
Socket
用于链接
为后续的事件发射设置一个修饰符,该修饰符将使事件数据仅在值为 true
时才压缩。如果您不调用该方法,则默认为 true
。
io.on("connection", (socket) => {
socket.compress(false).emit("uncompressed", "that's rough");
});
socket.disconnect([close])
断开此套接字连接。如果 close 的值为 true
,则关闭底层连接。否则,它只断开命名空间的连接。
io.on("connection", (socket) => {
setTimeout(() => socket.disconnect(true), 5000);
});
socket.emit(eventName[, ...args][, ack])
(覆盖 EventEmitter.emit
)
eventName
<string>
|<symbol>
args
<any[]>
ack
<Function>
- 返回
true
向由字符串名称标识的套接字发出事件。可以包含任何其他参数。所有可序列化数据结构都受支持,包括 Buffer
。
io.on("connection", () => {
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.emitWithAck(eventName[, ...args])
在 v4.6.0 中添加
eventName
<string>
|<symbol>
args
any[]
- 返回
Promise<any>
基于 Promise 的发出并期望从给定客户端确认的版本
io.on("connection", async (socket) => {
// without timeout
const response = await socket.emitWithAck("hello", "world");
// with a specific timeout
try {
const response = await socket.timeout(10000).emitWithAck("hello", "world");
} catch (err) {
// the client did not acknowledge the event in the given delay
}
});
上面的示例等效于
io.on("connection", (socket) => {
// without timeout
socket.emit("hello", "world", (val) => {
// ...
});
// with a specific timeout
socket.timeout(10000).emit("hello", "world", (err, val) => {
// ...
});
});
在接收方
socket.on("hello", (arg1, callback) => {
callback("got it"); // only one argument is expected
});
socket.eventNames()
继承自 EventEmitter
(以及此处未提及的其他方法)。有关 events 模块的 Node.js 文档,请参见。
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.in(room)
在 v1.0.0 中添加
是 socket.to(room) 的同义词。
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.listenersAny()
- 返回
<Function[]>
返回已注册的通配符监听器列表。
const listeners = socket.listenersAny();
socket.listenersAnyOutgoing()
在 v4.5.0 中添加
- 返回
<Function[]>
返回已注册的用于传出数据包的通配符监听器列表。
const listeners = socket.listenersAnyOutgoing();
socket.offAny([listener])
listener
<Function>
移除之前注册的监听器。如果未提供监听器,则会移除所有通配符监听器。
const myListener = () => { /* ... */ };
socket.onAny(myListener);
// then, later
socket.offAny(myListener);
socket.offAny();
socket.offAnyOutgoing([listener])
在 v4.5.0 中添加
listener
<Function>
移除之前注册的监听器。如果未提供监听器,则会移除所有通配符监听器。
const myListener = () => { /* ... */ };
socket.onAnyOutgoing(myListener);
// remove a single listener
socket.offAnyOutgoing(myListener);
// remove all listeners
socket.offAnyOutgoing();
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.onAny(callback)
callback
<Function>
注册新的通配符监听器。
socket.onAny((event, ...args) => {
console.log(`got ${event}`);
});
确认 不会被通配符监听器捕获。
socket.emit("foo", (value) => {
// ...
});
socket.onAnyOutgoing(() => {
// triggered when the event is sent
});
socket.onAny(() => {
// not triggered when the acknowledgement is received
});
socket.onAnyOutgoing(callback)
在 v4.5.0 中添加
callback
<Function>
为出站数据包注册新的通配符监听器。
socket.onAnyOutgoing((event, ...args) => {
console.log(`got ${event}`);
});
确认 不会被通配符监听器捕获。
socket.on("foo", (value, callback) => {
callback("OK");
});
socket.onAny(() => {
// triggered when the event is received
});
socket.onAnyOutgoing(() => {
// not triggered when the acknowledgement is sent
});
socket.once(eventName, listener)
继承自 EventEmitter
(以及此处未提及的其他方法)。有关 events 模块的 Node.js 文档,请参见。
socket.prependAny(callback)
callback
<Function>
注册新的通配符监听器。监听器将被添加到监听器数组的开头。
socket.prependAny((event, ...args) => {
console.log(`got ${event}`);
});
socket.prependAnyOutgoing(callback)
在 v4.5.0 中添加
callback
<Function>
为出站数据包注册新的通配符监听器。监听器将被添加到监听器数组的开头。
socket.prependAnyOutgoing((event, ...args) => {
console.log(`got ${event}`);
});
socket.removeAllListeners([eventName])
继承自 EventEmitter
(以及此处未提及的其他方法)。有关 events 模块的 Node.js 文档,请参见。
socket.removeListener(eventName, listener)
继承自 EventEmitter
(以及此处未提及的其他方法)。有关 events 模块的 Node.js 文档,请参见。
socket.send([...args][, ack])
args
<any[]>
ack
<Function>
- 返回
Socket
发送 message
事件。参见 socket.emit(eventName[, ...args][, ack]).
socket.timeout(value)
在 v4.4.0 中添加
设置后续事件发射的修饰符,当给定的毫秒数过去而没有收到客户端的确认时,回调将被调用并出现错误
socket.timeout(5000).emit("my-event", (err) => {
if (err) {
// the client did not acknowledge the event in the given delay
}
});
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
// Please use `io.to(socket.id).emit()` instead.
});
注意:广播时不支持确认。
socket.use(fn)
历史
版本 | 更改 |
---|---|
v3.0.5 | 恢复第一个实现。 |
v3.0.0 | 删除,改为使用 socket.onAny() 。 |
v1.7.2 | error 事件直接发送到客户端。 |
v1.6.0 | 第一个实现。 |
fn
<Function>
注册一个中间件,它是一个函数,对每个传入的 Packet
执行,并接收数据包和一个函数作为参数,该函数可以选择将执行延迟到下一个注册的中间件。
传递给中间件回调的错误将作为服务器端的 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();
}
});
});
标志
标志:'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
});
客户端


Client
类表示传入的传输(engine.io)连接。一个 Client
可以与属于不同 Namespace
的多个复用 Socket
关联。
属性
client.conn
<engine.Socket>
对底层 engine.io
Socket
连接的引用。
client.request
一个 getter 代理,返回对生成 engine.io 连接的 request
的引用。用于访问请求标头,例如 Cookie
或 User-Agent
。
引擎
Engine.IO 服务器,它管理 WebSocket / HTTP 长轮询连接。更多信息 这里.
其源代码可以在此处找到: https://github.com/socketio/engine.io
事件
事件:'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 | "Transport unknown" |
1 | "Session ID unknown" |
2 | "Bad handshake method" |
3 | "Bad request" |
4 | "Forbidden" |
5 | "Unsupported protocol version" |
事件:'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 });
}
});
事件:'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" });
}
});
另见
属性
engine.clientsCount
在 v1.0.0 中添加
当前连接的客户端数量。
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
用于生成新会话 ID 的函数。默认为 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);
engine.use(middleware)
在 v4.6.0 中添加
添加新的 Express 中间件.
io.engine.use((req, res, next) => {
// do something
next();
});
中间件将针对每个传入的 HTTP 请求(包括升级请求)调用。
使用 express-session
的示例
import session from "express-session";
io.engine.use(session({
secret: "keyboard cat",
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}));
使用 helmet
的示例
import helmet from "helmet";
io.engine.use(helmet());