【问题标题】:Get socket object获取套接字对象
【发布时间】:2021-08-04 22:39:56
【问题描述】:

我将 socket.io 与 redis 一起使用,我需要获取套接字对象,因为我需要访问在中间件期间添加的数据。

当我这样做时:

const { socketServer } = require('../../socket/socket');
const allSockets = await socketServer.myNamespace.adapter.sockets(new Set());

我只得到套接字 id,而不是套接字对象。如何获取套接字对象?

使用:
socket.io:4.0.1.
socket.io-redis: 6.1.0

更新

const socketServer = {
    _initialized: false,
    _IO: null,
    _myNamespace: null,
    get IO() {
        if (!socketServer._initialized) throw new Error('socketServer.create not called!');
        return socketServer._IO;
    },
    get myNamespace() {
        if (!socketServer._initialized) throw new Error('socketServer.create not called!');
        return socketServer._myNamespace;
    },
    create: (server) => {
        const { initMyNamespace } = require('./setupHandler');

        socketServer._IO = io(server, { cors: { origin: '*' } });

        const redisPort = config.get('redisPort');
        const redisHost = config.get('redisHost');

        const redisConnection = redisAdapter({ host: redisHost, port: redisPort });

        socketServer._IO.adapter(redisConnection);

        // inits
        socketServer._myNamespace = socketServer._IO.of('myNamespace');

        // Middlewares
        socketServer._myNamespace.use(auth);

        socketServer._myNamespace.on('connection', function (socket) {
            initMyNamespace(socket);
        });
    
        socketServer._initialized = true;
    },
};

在 api 调用中的另一个文件中:

router.post('/', async (req, res) => {
    const { socketServer } = require('../../socket/socket');

    let selectedSockets = [];
    const allSockets = await socketServer.myNamespace.adapter.sockets(new Set());
    
    const userCoordinates = req.body.coordinates;
    for (const currentSocketObj of allSockets) {
        if (isNear(userCoordinates, currentSocketObj.user.coordinates)) {
            const distanceToLocation = distanceCalc(userCoordinates, currentSocketObj.user.coordinates);
            currentSocketObj.distanceToLocation = distanceToLocation;
            selectedSockets.push(currentSocketObj);
        }
    }
    
    for (const currentSocketObj of selectedSockets) {
        currentSocketObj.emit('testing123', {distance: currentSocketObj.distanceToLocation} );
    }
});

【问题讨论】:

  • 您使用的是哪个版本的 socket.io(我问的是 v4 中的一些 API 更改)?
  • @jfriend00 socket.io: 4.0.1。 socket.io-redis: 6.1.0
  • 当你说你想得到“套接字对象”时,你是什么意思。如果这是一个服务器,那么在任何给定时间都有 N 个连接的套接字。另外,你用的是redis适配器和socket.io集群吗?
  • @jfriend00 我正在尝试访问具有握手的套接字项。我正在使用 redis 适配器。我以后会用socket.io集群
  • 请显示您尝试访问套接字的代码上下文,因为它可能已经在socket 的范围内。

标签: javascript node.js redis socket.io


【解决方案1】:

在 socket.io v4 中,你可以这样做:

// return all Socket instances
const sockets = await io.fetchSockets();

或者,如果你有一个socketID,你可以用这个来获取那个socket:

// return all Socket instances in the "room1" room of the main namespace
const sockets = await io.in(theSocketID).fetchSockets();

两个调用都返回一个可迭代的套接字。


如果(根据您的评论),您正在尝试获取正在连接的特定套接字,那么 socket 应该已经在范围内,基于第一次调用您的事件处理程序地方。如果您在上下文中显示该代码,我们可能会向您显示 socket 引用在其中。

【讨论】:

  • 使用redis时可以使用io.fetchSockets();吗?
  • @Jessica - 我相信是这样,但这不是您现在描述的问题的正确解决方案。您只需将原始事件处理程序中已经在范围内的socket 传递给其他模块中的函数。使用fetchSockets() 获取完整的套接字列表是没有意义的。这不会告诉您哪个套接字负责当前的握手。如果您在两个模块中向我们展示您的代码,我们可以提供准确的帮助。请停止拒绝展示您的实际代码 - 这就是我们需要帮助您的原因。
  • 是的,只是不想把问题搞砸了......发布了套接字的设置代码。我想获取所有套接字的代码在 api 请求中。我将根据里面的数据发送每个套接字特定的数据
  • @Jessica - 我不知道您想从内部引用 socket 的确切代码以及如何调用该代码。
  • @Jessica - 我在您的设置中没有看到任何关闭的内容。在我看来很好。我通常不会尝试抽象和隐藏在 io 服务器对象上易于使用的东西,因为这只是让调用者必须知道/学习新的 API,而不是使用完全令人满意的 socket.io API这已经存在,但这是设计意见的问题。
猜你喜欢
  • 2012-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-05
  • 1970-01-01
  • 2018-08-13
相关资源
最近更新 更多