【问题标题】:emitting to single client socket io 1.3.2发射到单个客户端套接字 io 1.3.2
【发布时间】:2015-02-09 15:14:44
【问题描述】:

我在这里查看了几个答案,但我认为他们指的是旧版本的 socket.io,因为他们的解决方案对我不起作用。我正在使用

将数据返回到浏览器中
io.emit('update', data)

但它会发送给所有客户端,因此当我转到相同的 URL 时,相同的数据会显示在多个窗口中。我是否必须在连接时将客户端 ID 存储在某处,还是可以在发出之前将其取回?请具体。我尝试了 SO 的其他一些解决方案,但我得到了很多 ReferenceError 'id' is not defined 或 sockets instead of socket。

服务器设置和连接:

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

app.get('/aPath', function (req, res, next) {
        res.writeHead(200)

    var data = {
        "val1":  req.query.val1,
        "val2":  req.query.val2,
        "val3":  req.query.val3,
        "val4":  req.query.val4,
        "val5":  req.query.val5,
        "val6":  req.query.val6,
    }

    /*console.log(io.sockets.id)*/

    //io.to(io.sockets.id).emit('update', data)
    //io.sockets.socket(id).emit('update', data)
    io.emit('update', data)
    res.end("OK")
})

io.on('connection', function (socket) {
    console.log('websocket user connected')
});

【问题讨论】:

  • 您必须以某种方式将 restful 客户端与套接字客户端关联起来。一旦你这样做了,你就可以发出你的数据了。
  • 我不确定我是否理解您的意思“将 RESTful 客户端与套接字客户端相关联”您能进一步解释一下吗?
  • 阅读我的回答。基本上确保您知道第三方客户端发送的信息是谁。如果您有 1000 个活跃用户,您希望将其发送给正确的用户,因此您必须将正确的套接字用户与第三方客户端的响应相关联。

标签: node.js sockets socket.io


【解决方案1】:

由于第三方客户端通过 RESTful 接口发送信息,因此您需要在该请求中以标头或查询字符串的形式包含客户端的参考数据。

我建议使用 Redis 来存储活动的套接字用户以供快速参考。这将允许您部署多个应用程序,这些应用程序使用单个 redis 实例来保持数据同步。您也可以在应用程序内存中执行相同的操作,但这不能很好地扩展。

首先,你需要使用中间件来认证用户并缓存socket.id

var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var redis = require('redis');

io.use(function(socket, next){
  // validate user
  // cache user with socket.id
  var userId = validatedUser;
  socket.handshake.userId = userId;
  redis.set(userId, socket.id, function (err, res) {
       next()
  });
});

接下来处理所有套接字通信

io.on('connection', function (socket) {
    console.log('websocket user connected');

    //next handle all socket communication
    socket.on('endpoint', function (payload) {
        //do stuff
        socket.emit('endpoint.response', {/*data*/});
    });

    //Then remove socket.id from cache
    socket.on('disconnect', function (payload) {
        //remove user.id from cache
        redis.del(socket.handshake.userId, function (err, res) {
             console.log('user with %s disconnected', socket.id);
        });
    });
});

处理第三方事件。

app.get('/aPath', function (req, res, next) {
    // get user from third party
    var userId = req.query.userId

    var data = {
        "val1":  req.query.val1,
        "val2":  req.query.val2,
        "val3":  req.query.val3,
        "val4":  req.query.val4,
        "val5":  req.query.val5,
        "val6":  req.query.val6,
    };

    // get cached socketId from userId
    redis.get(userId, function (err, socketId) {
        // return ok to third party;
        res.status(200).send("OK");
        only emit if socketid still exists
        if (err || !socketId) return;
        // now emit to user
        io.to(socketId).emit('update', data):
    });
});

【讨论】:

  • 我更新了我的帖子以包含更多关于 emit 语句的上下文。第三方将 get 请求和数据发送到 aPath,然后 websocket 将其发送回连接的客户端(不是发送 get 请求的同一客户端),在该客户端呈现数据。如何在该上下文中获取套接字 ID?
猜你喜欢
  • 2021-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-05
  • 2022-09-28
  • 1970-01-01
  • 2015-11-09
  • 1970-01-01
相关资源
最近更新 更多