Socket.IO - 如何为不同的 endpoints/rooms 获取不同的活跃用户列表?

Socket.IO - how to get different active user lists for different endpoints/rooms?

我正在写一个简单的基于socket.io(v1.3.6)的聊天程序。当用户使用他们的用户名登录时,他们可以在仪表板中看到几个聊天室,并通过不同的端点进入每个聊天室,即

http://localhost:8080/api/chats/room01.

用户可以在这些房间中的任何一个聊天。我想为每个房间创建一个活跃用户列表。 'active' 表示此用户现在已连接到套接字(在这个房间聊天)。

我看到很多问题已经发布,但仍然被他们几个孤立的词弄糊涂了。

在我当前的 server.js 中,我添加了这段代码:

var io = require('socket.io')(http);

io.on('connection', function(socket){

  console.log('a user connected: ' + socket.id);

  socket.on('disconnect', function(){
    console.log(socket.id + ' has disconnected from the chat.');
  });

});

总结一下,两个问题:

非常感谢。

更新:

我的服务器端代码:

io.of('/rooms/room01').on('connection', function(socket) {

  console.log("socket connected: ", socket.id);
  //....some more codes

});

我的客户端代码:

app.factory('socketio', ['$rootScope', function($rootScope) {
  'use strict';

  var socket = io.connect('http://localhost:8080/rooms/room01');
  return {

    on: function(eventName, callback) {
      socket.on(eventName, function() {
        var args = arguments;
        $rootScope.$apply(function() {
          callback.apply(socket, args);
        });
      });
    },

    emit: function(eventName, data, callback) {
      socket.emit(eventName, data, function() {
        var args = arguments;
        $rootScope.$apply(function() {
          if (callback) {
            callback.apply(socket, args);
          }
        });
      });
    }
  };
}]);

以上代码无效。但是以前当我使用默认命名空间时

io.of('/').on('connection', function(socket) {
  //...
}

var socket = io.connect('http://localhost:8080/');

效果很好。你能告诉我为什么吗?

How can I distinguish the socket connections for different rooms/endpoints?

在您的服务器上,有几种方法可以列出各个房间和每个房间的插座。以下是有关您可以在服务器上访问的各种数据的一些信息,然后您可以决定哪种方式是获取您想要的内容的最有效方式:

io.sockets.adapter.rooms

这是一个包含所有房间作为键的对象,这些房间目前至少有一个连接。这包含您的服务器称为 .join() 的两个房间,用于手动将套接字加入房间,并包含每个套接字自动加入的每个默认房间(具有 socket.id 的名称)。所以,如果你知道你有一个名为 "test" 的房间,那么你可以用 io.sockets.adapter.rooms['test'].

获得一个对象,每个房间作为键

io.sockets.connected

这是一个包含当前连接的每个套接字的对象,其中 socket.id 是对象中的键。因此,如果 id 是 vlPYz3EHUOe8vFitAAAJ,那么您可以访问该 id 的套接字对象作为 io.sockets.connected['vlPYz3EHUOe8vFitAAAJ']。您显然可以使用 for (var sock in io.sockets.connected) 类型的循环来迭代所有连接的套接字。然后,在该套接字对象内部,您可以通过以下方式查看它所在的房间:io.sockets.connected['vlPYz3EHUOe8vFitAAAJ'].rooms 这是它所在的房间名称数组。此房间名称数组将包括与 socket.id.

io.sockets.sockets

这是一组已连接的套接字,与使用 io.sockets.connected 相比,访问所有当前已连接的套接字可能是一种更简单的方法。就像上一节中描述的那样,一旦你有一个给定的连接插座,你就可以访问 socket.rooms 属性 来获取插座当前所在的房间数组。

对于特定的插座,您可以通过以下方式获取它所在的房间列表:

socket.rooms

这是给定插座当前所在的房间名称的数组。这包括与 socket.id 同名的自动房间名称,因此如果只是尝试,您可能想忽略该房间名称列出插座所在的常规房间。

How can I get active usenames instead of socket.id which could be different for the same user?

由于用户名是您指定的,与 socket.io 没有任何关系,因此您必须自己找到一种方法将用户名与套接字相关联。根据已知用户名的位置,您可以在不同的地方执行此操作。如果它已经存在于 cookie 中,那么您可以从以下位置获取它:socket.handshake.headers.cookie 这是在最初连接套接字时为该特定套接字设置的 cookie 的快照。

如果在最初连接套接字时通过其他方式知道用户名,您可以从其他机制获取它并将其保存为套接字对象的 属性:socket.username = 'xxx'; 然后你就可以随时从服务器端套接字对象访问它了。

这是我用来探索这些不同数据结构的一些服务器端诊断代码:

'use strict';
var express = require('express');
var app = express();
var server = app.listen(80);
var io = require('socket.io')(server);
app.use(express.static('public'));

io.on('connection', function(socket) {
    console.log("socket connected: ", socket.id);

    // list all connected sockets
    var list = io.sockets.sockets;
    console.log("Connected sockets:");
    list.forEach(function(s) {
        console.log("    socket.id = ", s.id);
    });

    socket.on('join', function(name) {
        socket.join(name);

        // list all rooms
        console.log("Active rooms:");
        var rooms = io.sockets.adapter.rooms;
        for (var room in rooms) {
            if (rooms.hasOwnProperty(room)) {
                console.log("     ", room);
            }
        }

        // list all rooms this socket is in:
        console.log("Active rooms for this socket:");
        io.sockets.connected[socket.id].rooms.forEach(function(room) {
            console.log("    ", room);
        });


    });

    socket.on('leave', function(name) {
        socket.leave(name);
    });

});