【问题标题】:socket.io to emit from express.js controller to specific client who called API endpointsocket.io 从 express.js 控制器发出到调用 API 端点的特定客户端
【发布时间】:2017-04-29 04:28:06
【问题描述】:

你好我的 StackOverflow 朋友们, 我从位于 express.js 控制器函数内的套接字发射,因为我需要在用户的配置文件完成后通知用户。

我需要向调用 API 端点并触发控制器功能的特定客户端发出。

知道如何最好地做到这一点吗?

我正在考虑在 API 调用中将 socket_id 从客户端发送到服务器?

谢谢!

编辑 我意识到问题在于 express.js 和 socket.io 不共享会话数据,它们没有连接到中间件中。这篇文章设计了一个解决方案。 socket.io and express 4 sessions

【问题讨论】:

  • 这里的关键是您必须能够识别是哪个客户端正在发送 API 调用,并且能够确定服务器端哪个 socket.io 连接是他们的。通常,您通过会话对象执行此操作,并且当他们与 socket.io 连接时,您将他们的套接字对象放入会话中。因此,当您收到 API 调用时,您可以进入会话对象以获取套接字或 socket.id,然后可以执行socket.emit()
  • 您在使用会话吗?如果有,是哪一个?
  • 是的,这就是我想要遵循的方法,将套接字 id 放入会话中并将其与 API 调用一起发送回服务器。是的,我确实使用了一个会话,但你所说的“哪个”是什么意思?问题是我似乎无法在客户端看到套接字 id 是什么,只能在服务器端看到。
  • 我的意思是你使用哪个模块来给你一个会话?快速会话? socket.id 仅在服务器上可用,除非您在消息中明确将其发送给客户端或将其放入 cookie 中。但是,您还没有解释为什么您甚至需要在客户端上使用它。
  • 好的,谢谢。是的,我使用快速会话。将套接字 ID 从客户端发送到服务器是我想象的一种方法,但我意识到这没有意义,而且套接字 ID 在客户端也不容易获得。一切都必须发生在服务器端。我意识到问题是由于 socket.io 和 express.js 没有共享会话。这篇文章设计了一个解决方案:stackoverflow.com/questions/23494016/…。或者,我设法使用会话令牌对每个套接字进行身份验证。然后我可以将套接字 id 关联到令牌(而不是会话 id)。

标签: node.js express socket.io


【解决方案1】:

在您的套接字处理程序中使用 socket.emit,如下所示:

var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);

io.on('connection', function(socket){
  socket.on('someEndpoint', function(message){
    socket.emit('someClientEndPoint', 'You sent a message to someEndpoint');
  });
});

【讨论】:

  • 这错过了他们想使用socket.emit(),但他们想从传入的 API 调用中使用它。
【解决方案2】:

以下实现解决了发起 API 请求的套接字通信问题。它遵循通过请求发送socketid的想法。当用户在同一浏览器中打开多个选项卡时共享会话变量不起作用,因为浏览器在选项卡之间分配了相同的 cookie/会话。

服务器代码

  socketio.on('connection', function(socket) {
    socket.address = `${socket.request.connection.remoteAddress}:${socket.request.connection.remotePort}`;

    //  USED TO SET THE SOCKET ID FOR THE REQUEST
    socket.emit('initialize', socket.id)


    socket.connectedAt = new Date();
}

客户代码
在 Angular 中,我设置了一个初始化事件来存储选项卡的特定套接字 ID

    this.socket.on('initialize', socketid => {
        console.log(socketid)
        this.socketid = socketid
    })


当请求发送到express时,我将socketid作为header发送

return this.$http({
    method: 'POST',
    withCredentials: true,
    host: '127.0.0.1',
    data: sim_data,
    port: 3000,
    responseType: "arraybuffer",
    headers: {
        "X-socketid": this.socketid
    },
    url: '/api/blah'
})

服务器代码
最后,当 express 处理 POST 或 get i 从 Header 发出到 socketid 时

    // GET SOCKET ID FROM HEADER
    var socket_id = req.headers['x-socketid']

    if (typeof socket_id !== 'undefined' && socket_id) {
        var io = req.app.get('io')
        io.sockets.connected[socket_id].emit('pyr', output)
    }

我的下一步是将其与用户授权集成。

【讨论】:

  • 我还没有实际测试过您的代码,但我可以看到以下问题:当服务器发出 socket.emit('initialize', socket.id) 时,它会将其发送给所有客户端,因此所有活动客户端都会捕获该事件并将其存储到他们的this.id。需要做的是,正如本文所建议的 [codershood.info/2016/01/24/…: 当套接字连接到客户端时,客户端应该将其 userId(或用户名)发送回服务器。当在服务器端捕获事件时,服务器可以将 userId 与 socketId 关联。
  • @Karl 实际上,上述实现中的 socket.emit 不会向所有客户端发出,因为 socketio.on.. 事件仅在“a”套接字连接并且事件中的套接字引用该事件时触发个别插座。 socketio.emit 会发送给所有活跃的客户端。
猜你喜欢
  • 1970-01-01
  • 2023-03-19
  • 2015-07-11
  • 2012-04-24
  • 1970-01-01
  • 1970-01-01
  • 2014-04-24
  • 2017-12-23
  • 1970-01-01
相关资源
最近更新 更多