Socket.IO - как получить список подключенных сокетов / клиентов?


Я пытаюсь получить список всех сокетов / клиентов, которые в настоящее время подключены.

io.sockets не возвращает массив, к сожалению.

Я знаю, что могу сохранить свой собственный список с помощью массива, но не думаю, что это оптимальное решение по двум причинам:

  1. избыточности. Socket.IO уже хранит копию этого списка.

  2. Socket.IO предоставляет метод для установки произвольных значений полей для клиентов (т. е.:socket.set('nickname', 'superman')) так Мне нужно будет идти в ногу с этими изменениями, если я буду поддерживать свой собственный список.

помочь?

27 135

27 ответов:

In Socket.IO 0.7 у вас есть clients метод на пространствах имен, это возвращает массив всех подключенных сокетов.

API для без пространства имен:

var clients = io.sockets.clients();
var clients = io.sockets.clients('room'); // all users from room `room`

для пространства имен

var clients = io.of('/chat').clients();
var clients = io.of('/chat').clients('room'); // all users from room `room`

надеется, что это поможет кому-то в будущем

Примечание: Данное Решение только работает с версией до 1.0

Socket.io 1.4

Object.keys(io.sockets.sockets); дает вам все подключенные розетки.

гнездо.Ио 1.0 По состоянию на socket.io 1.0, фактический принятый ответ больше не действителен. Поэтому я сделал небольшую функцию, которую я использую в качестве временного исправления:

function findClientsSocket(roomId, namespace) {
    var res = []
    // the default namespace is "/"
    , ns = io.of(namespace ||"/");

    if (ns) {
        for (var id in ns.connected) {
            if(roomId) {
                var index = ns.connected[id].rooms.indexOf(roomId);
                if(index !== -1) {
                    res.push(ns.connected[id]);
                }
            } else {
                res.push(ns.connected[id]);
            }
        }
    }
    return res;
}

Api для нет пространства имен становится

// var clients = io.sockets.clients();
// becomes : 
var clients = findClientsSocket();

// var clients = io.sockets.clients('room');
// all users from room `room`
// becomes
var clients = findClientsSocket('room');

Api для пространство имен будет :

// var clients = io.of('/chat').clients();
// becomes
var clients = findClientsSocket(null, '/chat');

// var clients = io.of('/chat').clients('room');
// all users from room `room`
// becomes
var clients = findClientsSocket('room', '/chat');

также смотрите это обзоры вопрос, в котором я даю функцию, которая возвращает сокеты для данной комнаты.

function findClientsSocketByRoomId(roomId) {
var res = []
, room = io.sockets.adapter.rooms[roomId];
if (room) {
    for (var id in room) {
    res.push(io.sockets.adapter.nsp.connected[id]);
    }
}
return res;
}

Socket.io 0.7

API для пространство имен:

var clients = io.sockets.clients();
var clients = io.sockets.clients('room'); // all users from room `room`

на пространство имен

var clients = io.of('/chat').clients();
var clients = io.of('/chat').clients('room'); // all users from room `room`

Примечание: так как это кажется socket.io API склонен к нарушению, и некоторые решения полагаются на детали реализации, это может быть вопрос отслеживания клиентов самостоятельно:

var clients = [];

io.sockets.on('connect', function(client) {
    clients.push(client); 

    client.on('disconnect', function() {
        clients.splice(clients.indexOf(client), 1);
    });
});

после того, как гнездо.Ио 1.0 мы не можем использовать

io.sockets.clients(); 
or
io.sockets.clients('room'); 

Использование Socket.IO 1.x:

получить массив подключенных клиентов:

io.engine === io.eio // => true
Object.keys(io.engine.clients) // => [ 'US8AxrUrrDF_G7ZUAAAA', 'Ov2Ca24Olkhf2NHbAAAB' ]
Object.keys(io.eio.clients)    // => [ 'US8AxrUrrDF_G7ZUAAAA', 'Ov2Ca24Olkhf2NHbAAAB' ]

получить количество подключенных клиентов:

io.engine.clientsCount // => 2
io.eio.clientsCount    // => 2

очень просто в socket.io 1.3:

io.sockets.sockets - это массив, содержащий объекты, подключенные в розетку. Если вы сохранили имя пользователя в каждом сокете, вы можете сделать:

io.sockets.sockets.map(function(e) {
    return e.username;
})

бум. У вас есть имена всех подключенных пользователей.

Я прошел через эту боль сегодня. Socket.io будет намного лучше, если они смогут сделать надлежащую документацию для своего API.

в любом случае, я попытался заглянуть в io.сокеты и нашел ряд вариантов, которые мы можем использовать:

io.sockets.connected //Return {socket_1_id: {}, socket_2_id: {}} . This is the most convenient one, since you can just refer to io.sockets.connected[id] then do common things like emit()
io.sockets.sockets //Returns [{socket_1}, {socket_2}, ....]. Can refer to socket_i.id to distinguish
io.sockets.adapter.sids //Return {socket_1_id: {}, socket_2_id: {}} . Looks similar to the first one but the object is not actually the socket, just the information.

// Not directly helps but still relevant
io.sockets.adapter.rooms //Returns {room_1_id: {}, room_2_id: {}}
io.sockets.server.eio.clients //Return client sockets
io.sockets.server.eio.clientsCount //Return number of connected clients

кроме того, обратите внимание, что при использовании socket.io с пространством имен, вышеуказанные методы будут ломаться с момента ввода-вывода.сокеты становятся массивом вместо объекта. Чтобы решить, просто замените io.сокеты по io (т. е. io.розетки.подключен становится Ио.связанный, Ио.розетки.адаптер.комнаты становится Ио.адаптер.комнаты...)

проверено на socket.io 1.3.5

Я думаю, что мы можем получить доступ к объекту сокета с сервера, и вы можете назначить псевдоним и указать его идентификатор сокета,

io.sockets.on('connection',function(socket){ 
    io.sockets.sockets['nickname'] = socket.id;
    client.on("chat", function(data) {      
        var sock_id = io.sockets.sockets['nickname']
        io.sockets.sockets[sock_id].emit("private", "message");
    });    
});

On disconnect удалите Ник из io.sockets.sockets.

Это лучший способ получить к нему доступ socket.io 1.3

Object.keys(socket.adapter.rooms[room_id])

для тех, кто просто хочет подсчитать количество подключенных клиентов, я считаю, что это сделает это:

io.sockets.manager.server.connections

гнездо.Ио 1.4.4

пример кода для вас.

function get_clients_by_room(roomId, namespace) {
        io.of(namespace || "/").in(roomId).clients(function (error, clients) {
            if (error) { throw error; }
            console.log(clients[0]); // => [Anw2LatarvGVVXEIAAAD]
            console.log(io.sockets.sockets[clients[0]]); //socket detail
            return clients;
        });
    }

Я думаю, поможет кому-то этот блок кода.

версия +2.0

в версии + 2.0 вы указываете пространство имен / комнату / узел, к которому вы обращаетесь.

как и в случае широковещания, по умолчанию используются все клиенты из пространства имен по умолчанию ('/'):

const io = require('socket.io')();  
io.clients((error, clients) => {
      if (error) throw error;
      console.log(clients); // => [6em3d4TJP8Et9EMNAAAA, G5p55dHhGgUnLUctAAAB]
});

возвращает список идентификаторов клиентов, подключенных к определенному пространству имен (по всем узлам, если применимо).

const io = require('socket.io')();
io.of('/chat').clients((error, clients) => {
     if (error) throw error;
     console.log(clients); // => [PZDoMHjiu8PYfRiKAAAF, Anw2LatarvGVVXEIAAAD]
});

пример, чтобы получить все клиенты в комнате пространства имен:

const io = require('socket.io')();
io.of('/chat').in('general').clients((error, clients) => {
      if (error) throw error;
      console.log(clients); // => [Anw2LatarvGVVXEIAAAD] 
});

Это из официальной документации:Socket.IO сервер-API

In Socket.IO 1.4

чтобы получить массив всех подключенных пользователей :

var allConnectedClients = Object.keys(io.sockets.connected);// This will return the array of SockeId of all the connected clients

чтобы получить количество всех клиентов:

var clientsCount = io.engine.clientsCount ; // This will return the count of connected clients

по состоянию на socket.io 1.5, обратите внимание на изменение от indexOf, которое, как представляется, обесценивается и заменяется valueOf

function findClientsSocket(roomId, namespace) {
    var res = [];
    var ns = io.of(namespace ||"/");    // the default namespace is "/"

    if (ns) {
        for (var id in ns.connected) {
            if (roomId) {
                //var index = ns.connected[id].rooms.indexOf(roomId) ;
                var index = ns.connected[id].rooms.valueOf(roomId) ; //Problem was here

                if(index !== -1) {
                    res.push(ns.connected[id]);
                }
            } else {
                res.push(ns.connected[id]);
            }
        }
    }
    return res.length;
}

для socket.io версия 2.0.3, следующий код работает:

function findClientsSocket(io, roomId, namespace) {
    var res = [],
        ns = io.of(namespace ||"/");    // the default namespace is "/"

    if (ns) {
        for (var id in ns.connected) {
            if(roomId) {
                // ns.connected[id].rooms is an object!
                var rooms = Object.values(ns.connected[id].rooms);  
                var index = rooms.indexOf(roomId);
                if(index !== -1) {
                    res.push(ns.connected[id]);
                }
            }
            else {
                res.push(ns.connected[id]);
            }
        }
    }
    return res;
}

ВКЛ socket.io 1.3 я сделал это в 2 строки

var usersSocketIds = Object.keys(chat.adapter.rooms['room name']);
var usersAttending = _.map(usersSocketIds, function(socketClientId){ return chat.connected[socketClientId] })

гнездо.Ио 1.7.3(+) :

function getConnectedList ()
{
    let list = []

    for ( let client in io.sockets.connected )
    {
        list.push(client)
    }

    return list
}

console.log( getConnectedList() )

// returns [ 'yIfhb2tw7mxgrnF6AAAA', 'qABFaNDSYknCysbgAAAB' ]

Я считаю, что вы можете получить доступ к этому из свойства менеджера сокета?

var handshaken = io.manager.handshaken;
var connected = io.manager.connected;
var open = io.manager.open;
var closed = io.manager.closed;

Я вижу много хороших ответов здесь и много где очень полезно, но не совсем то, что мне нужно. Я использую сокеты для функции pubsub, в которой заинтересованный клиент может слушать любые изменения в данной записи.

моя конкретная проблема заключалась в том, что один и тот же сокет присоединялся к одной и той же комнате несколько раз. Решение этой проблемы состояло в том, чтобы проверить, есть ли у сокета комната внутри его номера.

var room = myObj.id.toString();
if (socket.rooms.indexOf(room) === -1) {
    socket.join(room);
    socket.emit('subscribed', {to : room});
} else {
    console.log("Already in room");
}

надеюсь, это кому-то поможет.

начиная с версии 1.5.1, я могу получить доступ ко всем сокетам в пространстве имен с помощью:

var socket_ids = Object.keys(io.of('/namespace').sockets);
socket_ids.forEach(function(socket_id) {
    var socket = io.of('/namespace').sockets[socket_id];
    if (socket.connected) {
        // Do something...
    }
});

по какой-то причине они используют простой объект вместо массива для хранения идентификаторов сокетов.

для версии 2.3 это работает, и это поможет вам сокет тоже, мне кажется, что socketIo меняется слишком быстро и очень мало читаемой документации после ее использования в течение некоторого времени.

ioSite.of('/').in(roomId).clients((error, clients) => {
    if (error) throw error;
    for (var i=0;i<clients.length;i++) {
        clientId=clients[i];
        console.log(clientId);

        // load the socket of your namespace
        var socket=ioSite.of('/').in(roomId).connected[clientId]
        console.log(socket.constructor.name);
        console.log(socket.id);
    }
});

все равно это не кажется правильным, так как у меня всегда есть это чувство с сокетом Io как-то

для кластерного режима, используя redis-adaptor

io.in(<room>).clients(function(err, clients) {

});

поскольку каждый сокет сам по себе является комнатой, поэтому можно найти, существует ли сокет, используя то же самое.

вот быстрый способ преобразования хэша подключенных сокетов из пространства имен в массив с помощью генераторов ES6 (применяется к socket.io >= v1. 0. 0):

io.on('connection', function(socket) {
  var hash = io.of('/').connected
  var list = null

  hash[Symbol.iterator] = function*() {
    // for..of loop to invoke Object.keys() default iterator
    // to get the array values instead of the keys
    for(var id of Object.keys(hash)) yield hash[id]
  }

  list = [...hash]
  console.log(Array.isArray(list)) // true
})

Это самый простой способ Socket.IO 1.0+, если вы не используете пространства имен или комнаты.

io.nsps["/"].sockets.length

это смотрит на пространство имен по умолчанию и определяет длину массива сокетов, без необходимости использовать Object.keys()

Я не знаю, если это продолжается. Но что-то вроде этого я в конечном итоге использовал (я держу сессии объект на каждом подключенном сокете, который в свою очередь содержит имя пользователя и другую информацию:

var connectedUsers = Object.keys(io.sockets.connected).map(function(socketId) {
    return io.sockets.connected[socketId].session.username;
});

Если проект имеет socket.io кластер это означает socket.io-redis используется адаптер.

Если случай, как указано выше, получение всех подключенных сокетов id процесс должен быть применен черезsocket.io-redis адаптер. Примеры ниже могут быть использованы для этого;

io.of('/').adapter.clients(function (err, clients) {
  console.log("clients: ", clients); // an array containing all connected socket ids
});


io.of('/').adapter.allRooms(function (err, rooms) {
  console.log("all rooms: ", rooms);
});

посетите страницуsocket. io-redis github для более подробной информации.

var Client = require("socket.io").listen(8888); //port listening

//This is the best way.

var connection = Client.engine.clientsCount

socket.io@1.7.3

я использовал объект.Ключи для подключения массива сокетов. Затем в том же массиве итерации с функцией map построить новый массив объектов

var connectedUsers = Object.keys(io.sockets.connected).map(function(socketId) {
    return { socket_id : socketId, socket_username: io.sockets.connected[socketId].username };
});

// test
console.log(connectedUsers);

возможно, этот ответ может помочь получить массив идентификаторов сокетов / имен пользователей.

v. 10

var clients = io.nsps['/'].adapter.rooms['vse'];
var count = clients.length;  // count
var sockets = clients.map((item)=>{  // all sockets room 'vse'
       return io.sockets.sockets[item];
      });
sample >>>
var handshake  = sockets[i].handshake; 
handshake.address  .time .issued ... etc.