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

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

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

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

  • Избыточность

    . Socket.IO уже хранит копию этого списка.

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

    /li >

Справка

Ответ 1

В 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

Ответ 2

Socket.io 1.4

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

Socket.io 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`

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

var clients = [];

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

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

Ответ 3

После socket.io 1.0 мы не можем использовать

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

больше. Вместо этого вы можете использовать следующие

var clients_in_the_room = io.sockets.adapter.rooms[roomId]; 
for (var clientId in clients_in_the_room ) {
  console.log('client: %s', clientId); //Seeing is believing 
  var client_socket = io.sockets.connected[clientId];//Do whatever you want with this
}

Ответ 4

Использование 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

Ответ 5

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

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

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

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

Ответ 6

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

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

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.sockets становится массивом вместо объекта. Чтобы разрешить, просто замените io.sockets на io (i.e io.sockets.connected станет io.connected, io.sockets.adapter.rooms станут io.adapter.rooms...)

Протестировано на socket.io 1.3.5

Ответ 7

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

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");
    });    
});

В disconnect удалите псевдоним из io.sockets.sockets.

Ответ 8

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

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

Ответ 9

Для тех, кому просто нужен COUNT подключенных клиентов, я считаю, что это сделает:

io.sockets.manager.server.connections

Ответ 10

Socket.io 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;
        });
    }

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

Ответ 11

on socket.io 1.3 Я выполнил это в 2 строках

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

Ответ 12

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

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;
}

Ответ 13

В 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

Ответ 14

Socket.io 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' ]

Ответ 15

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

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

Ответ 16

Я вижу много хороших ответов здесь и многих, где довольно полезно, но не совсем то, что мне нужно. Я использую сокеты для функции 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");
}

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

Ответ 17

Начиная с версии 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...
    }
});

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

Ответ 18

Для версии 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 как-то

Ответ 19

Вот быстрый способ преобразования хэша подключенных сокетов из пространства имен в массив с использованием генераторов 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
})

Ответ 20

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

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

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

Ответ 21

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

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

Ответ 22

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

Если такой случай, как и выше, получение всех процессов с подключенными сокетами должен быть применен через адаптер 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.

Ответ 23

Версия +2.0

В версии +2.0 вы указываете пространство имен/номер/ node, с которым вы запрашиваете.

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

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 Server-API

Ответ 24

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

//Это лучший способ.

var connection = Client.engine.clientsCount

Ответ 25

Для режима кластера с использованием redis-adapter

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

});

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