我也遇到了同样的问题,猜测在socket.io 4.x版本中示例代码发生了什么。
在这个示例中,他们使用中间件(use函数注册中间件)。
namespace.use((socket, next) => {
const sessionID = socket.handshake.auth.sessionID;
const {userId, username} = yourFunction();
socket.sessionID = sessionID;
socket.userID = session.userID;
socket.username = session.username;
next();
});
当套接字连接到服务器时,中间件将被执行。
然后,您可以使用数据。
注意- Socket.IO参考告诉我们使用socket.data以此为目的。
namespace.on('connection', socket => {
socket.emit("join", `${socket.username} has been joined`);
})
如果您使用多个服务器,则必须牢记数据仅适用于该服务器。
在多服务器环境中,您需要一个单一的数据源,该数据源将由套接字服务器使用。
namespace.use(async (socket: Socket & { sessionID?: string, userID?: string, username?: string }, next) => {
const sessionID = socket.handshake.auth.sessionID;
if (sessionID) {
const session = await someFunctionToRetrieveSession(sessionID);
if (session) {
socket.sessionID = sessionID;
socket.userID = session.userID;
socket.username = session.username;
return next();
}
}
const username = socket.handshake.auth.username;
if (!username) {
return next(new Error("invalid username"));
}
socket.sessionID = randomId();
socket.userID = randomId();
socket.username = username;
next();
});
还有一件事,据我所理解,当命名空间使用函数仅适用于命名空间时,如果您的客户端使用的是不同于默认值的其他命名空间,则默认('/')使用函数将不会被调用。
//client side
io("/chat");
...
//server side
io.use() // == io.of('/').use() will not be called
io.of('/chat').use() // only will be called
感谢示例的作者使用redis实现了sessionStorage,请参考this example code
有了这个信息,我猜测socket.io服务器会将socket的信息保存在内存中,并设置一个属性来保存socket及其相关数据。当socket再次连接时,服务器会检索socket及其相关数据。但由于这发生在内存中,所以无法在其他服务器之间共享信息,因此您必须找到一种与其他服务器共享数据的方法(例如redis)。