【问题标题】:Keep Reference to Connected Sockets Per User保持对每个用户连接的套接字的引用
【发布时间】:2013-05-13 16:40:55
【问题描述】:

我有一个(为了清楚起见)聊天。

用户可以登录,写消息,其他人会看到[name]:[message]

我不想每次写socket.emit('say', message);时都发送用户名和ID,因为那是多余的,所以我在服务器上做的事情是这样的:

var io = require("socket.io").listen(server),
    sockets = {};

io.sockets.on('connection', function (socket){
    socket.on('savePersonToSocket', function(user){
        socket.user = user;
        sockets[user.id] = socket;
    }
    socket.on('doSomething', doSomething);
});

// must be outside of 'connection' since I have TONS of these in a much more 
//complex structure and I don't want to create them all per user connection.
function doSomething(){
    ...
    sockets[userID].emit('foo'); // how to get the userID at this point?
    ...
}

那么,此时我将如何获取用户 ID?

注意事项:

  • 对于每个登录并连接其 Facebook 帐户的用户,客户端将告诉服务器保存此人的姓名和 ID。

我想用一个 cookie 来保存用户的姓名和 ID,服务器会通过读取 cookie 知道它是哪个用户,但这有点丑陋的解决方案:每次都发送该信息是多余的.

我还可以(以某种方式)劫持“on”函数并添加可以知道用户身份的功能,因为无论如何所有“on”侦听器都必须驻留在“connection”侦听器中。

【问题讨论】:

  • 不获取用户 ID。拿到插座。 socketevents.forEach(function(ev){ socket.on(ev.name, ev.fn.bind(socket)); });
  • @FizzyTea - 请把它写成完整的答案?我不明白你的答案的上下文..如何使用它。
  • 这只是一个建议,因此是评论而不是答案。也许我应该更好地表达我只是猜测。你比我更了解你的代码库,所以如果你看不出它是如何应用到你身上的,那么也许这不是正确的方法。

标签: javascript node.js socket.io


【解决方案1】:

我知道你问这个问题已经很久了,但就在 4 年前,我发布了一个用于 node js、express 和 socket.io 的模块,它可以管理你想要的东西。查看用法和示例,希望对您有所帮助!

你可以通过npm socket.io.users This is a node js module for socket.io applications. One user per client.安装它

你可以看一些usage code on this answer

【讨论】:

    【解决方案2】:

    这个怎么样:

    var io = require("socket.io").listen(server),
        sockets = {};
    
    io.sockets.on('connection', function (socket){
        socket.on('savePersonToSocket', function(user){
            socket.user = user;
            sockets[user.id] = socket;
        }
        socket.on('doSomething', function() { doSomething(socket.user) });
    });
    
    // must be outside of 'connection' since I have TONS of these in a much more 
    //complex structure and I don't want to create them all per user connection.
    function doSomething(user){
        ...
        sockets[user.id].emit('foo');
        ...
    }
    

    【讨论】:

    • 这是最糟糕的方法...而且您还忘记将参数从doSomething 订阅者传递给doSomething 回调(您只传递了套接字)。反正我的答案是对的
    • 嗯,我通过了socket.user。提醒我不要再帮你了。
    • 我建议这样做是因为您称自己的解决方案“丑陋”。
    • 所以你提出了更丑陋的建议;)
    【解决方案3】:

    理论上,像这样丑陋的东西应该可以工作,但是恕我直言,apply 的用法很糟糕,而且缺少简单的函数指针会使代码更丑

    var io = require("socket.io").listen(server);
    
    io.sockets.on('connection', function (socket){
        socket.on('savePersonToSocket', function(user){
            socket.user = usr;
        }
    
        // No more simple function pointers....
        socket.on('doSomething', function(){
           // pass the Socket as the scope
           doSomething.apply(socket, arguments);
        });
    
    });
    
    function doSomething(){
        ...
        this.emit('foo');
        ...
    }
    

    【讨论】:

      【解决方案4】:

      可能发生的情况是用户连接到您的聊天应用程序,所以在这里

      io.sockets.on('connection', function (s){
        socket = s; // cache for later usage
      

      您将“他的套接字”分配给变量socket,它与上下文无关,它是独立的。现在假设第二个用户到达,socket 被重新分配给第二个用户,但是如果你得到一个savePersonToSocket 事件,那么socket 将被使用,这对每个人都是一样的,更详细的是与最后连接的用户相关。

      您无需保留对s 的引用,当您将有很多用户连接到您的应用程序时,您可能必须处理这个问题,但解决方案将与您的方法大不相同。

      编辑:另一种方法是映射用户 ID 和 sockets:

      // this assumes that the name of a user is unique
      var userSocket = {};
      
      io.sockets.on('connection', function (s){
        socket.on('savePersonToSocket', function(user){
          userSocket[user.name] = s;
        }
      

      所以基本上你是说你不想将userID 传递给doSomething 事件有效负载?因为这对我来说似乎是一个有效的解决方案,它不是多余的,它是让服务器知道它正在处理的用户的最简单方法。其他解决方案可能更优雅,但我怀疑它们是否像这个一样简单且易于维护。

      【讨论】:

      • 是的,确实如此。嗬,这个问题的耻辱让我丧命:)
      • 这没有什么可耻的,别担心 ;)
      • 是的,在使用了 8 年的 javascript 之后,我有时会觉得自己像个婴儿在用 Node 写东西,猜测东西是如何工作的,因为我需要考虑许多不同的用户,而不仅仅是一个单一的用户。
      • 实际上,我确实需要缓存套接字,因为我有全局函数,每次调用它们时都需要访问每个特定的套接字。
      • 好的,那么用户和套接字之间的映射呢?
      【解决方案5】:

      你不能从字面上保存连接,它经常变化。 但是您可以保存 socket.id。你有 io.sockets.sockets[socketid] 这可能就是你要找的。​​p>

      您可以保存 id 和名称的数组并根据需要重复使用它们。

      (请注意,与流程相关的变量会使其无法扩展。但第一次你可以不关心它:)

      您还有与套接字相关的存储对象 socket.handshake socket.handshake.somevariable=simple_value_a_string_or_a_number

      【讨论】:

      • 我可以保存套接字,它只是一个人在系统中时创建的对象。我在最早的尝试中确实保存了套接字 ID,但我仍然看不到我以后如何才能找出哪个用户属于哪个套接字,而无需用户在每次“发射”时传递他的 ID。顺便说一句,socket.handshake 有什么帮助?
      • 是的,我实际上可以保存套接字的 ID(过去,当用户断开连接并再次连接时,我遇到了问题,他们以前的套接字 ID 没有任何意义,所以我会更新其对应套接字的 ID 并跟踪所有内容。
      【解决方案6】:

      如果你可以在一个帐户下保存套接字可以坐几个人,例如,这样的系统将是:

      var socketsList
      io.sockets.on('connection', function (socket) {
         socket.on('auth', function (data) {
            // request to database
          if ( ! (UNIQUE_ID in socketsList)) {
               socketsList[UNIQUE_ID] = {};
               socketsList[UNIQUE_ID][socket.id] = socket;
         });
      });
      
      // ONEXIT - BROWSER EVENT
      var onExit = function () { socket.emit('exit', { UNIQUE_ID : 123}) }
          window.onunload = onExit;
      // 
      
      socket.on('exit', function (data) {
         delete socketsList[UNIQUE_ID][socket.id]
      })
      

      如果我错了,请纠正我

      【讨论】:

      • 对不起,我不小心。然后这是未来:)
      • 我看不出这对解决问题有何帮助
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多