Socket.IO-接続されているソケット/クライアントのリストを取得するにはどうすればよいですか?


159

現在接続されているすべてのソケット/クライアントのリストを取得しようとしています。

io.sockets 残念ながら、配列を返しません。

配列を使用して自分のリストを保持できることはわかっていますが、これが2つの理由で最適な解決策であるとは思われません。

  1. 冗長性。Socket.IOはすでにこのリストのコピーを保持しています。

  2. Socket.IOは、クライアント(つまり:)に任意のフィールド値を設定するメソッドを提供socket.set('nickname', 'superman')するため、自分のリストを維持する場合は、これらの変更に対応する必要があります。

助けて?


io.socketsを配列に変換できませんか?
mak

2
0.7.6では、io.sockets.socketsは単純なハッシュオブジェクトですid => socket
mak

1
私はそれに気づきましたが、奇妙な動作をしています(標準のソケットオブジェクトのようには見えません)。たとえば、pastebin.com / fxuzVckSを試しましたが、ソケットオブジェクトに 'get'メソッドが含まれていないと言っています。
アンディヒン

3
socketID、io.sockets.sockets[socket]ソケットです。
mak

2
最初の引数はerr、メモリストアを使用している場合は常にnullです。.get('nickname', function(err, nickname) { ... })
mak

回答:


173

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より前のバージョンでのみ機能します


2020年3月6日更新

1.x以降では、このリンクを参照してください:socket.ioのチャットルームに何人がいるかを取得する


3
クライアントメソッドは1.0で削除されたと思います...現時点でチェックアウトしています...
markyzm

7
それは完全な書き直しなので、1.0ではほとんどすべてを落としました。しかし、1.0は何年もの間リリースされていませんでした。1.0ではconnected、名前空間のオブジェクトを使用する必要があります。
3rdEden 2014

6
@ 3rdEden、名前空間の接続されたオブジェクトを使用するための構文は何ですか?var clients = io.sockets.connected();明らかに動作しません。ありがとう
Kaya Toast 14


TypeError:fn.bindは関数ではありません
Iman Marashi

101

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`

注: socket.io APIは壊れやすい傾向があり、一部のソリューションは実装の詳細に依存しているため、クライアントを自分で追跡することが問題になる可能性があります。

var clients = [];

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

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

3
これありがとう。彼らがこの機能を削除したことに驚いています。
タイラースコット

1
@TylerScott私も、特にこれが彼らの移行ガイドでカバーされていないことを考えると(私が何かを見逃していない限り)。 socket.io/docs/migrating-from-0-9
nha

@nha、これは私にとっては機能しませんが、ソケットの配列の代わりに0、1、2などの整数の配列を返します。何か案は?
ThePixelPony 2014

複数ノードの場合はどうですか?Redisストアで複数のノードを使用しているため
John Nguyen

3
あなたが答える@nhaは正確ですが、redisストアサーバーを持つ複数のノードでは機能しません。1つのノードのプロセスから、ns.connected [id]を使用してソケットが接続されているかどうかを確認できない
John Nguyen

46

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
}

3
私の変更var clients_in_the_room = io.sockets.adapter.rooms[roomId].sockets
ファビオ・Zangirolami

37

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

32

socket.io 1.3では非常に単純です。

io.sockets.sockets-接続されたソケットオブジェクトを含む配列です。ユーザー名を各ソケットに保存した場合、次のことができます。

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

ブーム。接続しているすべてのユーザーの名前があります。


2
ありがとう!単純化のために+1。この方法と、たとえばジョセフ・ディクストラの答えに違いがあるかどうか知っていますか?(Object.keys(io.engine.clients)
cyclingLinguist 2015年

4
これはv1.4.5では機能しません。まだ解決策に取り組んでいます
Nuno Furtado 2016

見つけましたか?\
ocram

2
例外TypeError:io.sockets.sockets.mapは関数ではありません
キラリーイシュト

23

今日、私はこの苦痛を経験しました。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に置き換えるだけです(つまり、io.sockets.connectedはio.connectedになり、io.sockets.adapter.roomsはio.adapter.roomsになります...)

socket.io 1.3.5でテスト済み


1
@Зелёный名前空間を使用していない場合に機能します。名前空間を使用している場合は、io.server.eio.clientsCountに変更します
Thanh Nguyen

2
はい、公式ドキュメントは大幅に改善される可能性があります
CodeAndCats

18

バージョン+2.0

バージョン+2.0では、クエリの対象となる名前空間/ルーム/ノードを指定します。

ブロードキャストと同様に、デフォルトはデフォルトの名前空間( '/')のすべてのクライアントです。

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

特定の名前空間に接続されているクライアントIDのリストを取得します(該当する場合はすべてのノード間)。

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


1
すべてのソケットオブジェクトを表示する方法はありますか?たとえば、socket.username接続時に各ソケットにプロパティを追加した場合、これらのすべてのソケットオブジェクト(各ソケットに追加したカスタムプロパティを含む)を表示する方法はありますか?(参考までに、私は現在クライアントが接続するときにグローバルオブジェクト変数を使用して追加のソケット情報を保存しています-その設定方法を尋ねるのではなく、すべてのソケットオブジェクトを「デフォルト」で表示する方法があるかどうかを知りたいだけです) 。
user1063287

1
うーん、この回答ごとに、私はあなたが持つすべての接続のソケットを見ることができると思うconsole.log(io.sockets.connected)-各プロパティの値は、これらのプロパティが含まれている「ソケットオブジェクト」であるオブジェクトのようですnspserveradaptorid(文字列)、 、clientconnroomsacks、、connected 、、、、、、最終的に私は、接続上の各ソケットに追加するカスタムプロパティです。disconnectedhandshakefnsflags_rooms_events_eventsCountusername
user1063287

17

サーバーからソケットオブジェクトにアクセスでき、ニックネームを割り当てて、そのソケットIDをポイントできると思います。

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


「client.on」の目的は何ですか?このようなコードを使用できますか(1ソケットからのデータのみを受け入れます)?: io.sockets.sockets [sock_id] .on( 'newmessage'、function(data){console.log(data)});
、ホーク

9

これは、socket.io 1.3でアクセスする最良の方法です。

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


この例を共有させてください var room = io.sockets.adapter.rooms[room_id]; var connections = _.map(Object.keys(room), function(socketId){ return (io.sockets.connected[socketId].connected == true) });
Hany Alsamman 2015年

5

接続されたクライアントのCOUNTを必要とするだけの場合は、これでうまくいくと思います。

io.sockets.manager.server.connections


接続されたクライアントの数ではなく、テスト済みです。(もう少し)
mrzmyr 2012年

5
正確なカウントの使用を取得するためio.sockets.clients().length
Ivo

2
現在、両方とも動作io.sockets.manager.server.connectionsio.sockets.clients().lengthません。これは私にとっては有効でした-カウントのみ- io.engine.clientsCountおよびクライアントのリスト- io.engine.clientsCount。この方法で3年以上滞在しているためです。接続情報を取得する信頼できる方法のようです。(Joseph Dykstraの回答に基づく)
Aswin Ramakrishnan 2017

5

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

私は誰かがこのコードブロックを助けると思います。


4

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

私は確認しているのバージョン1.5.1でこの作品socket.io
セバスチャン・

3

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.5ではありません!現在1.4.8です
leszek.hanusz

@MoleIsKing Obrigado amigo!

2

socket.io 1.3で私は2行でこれを達成しました

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

2

Socket.io 1.7.3(+):

関数getConnectedList()
{
    リストをみましょう= []
    
    for(クライアントにio.sockets.connectedを許可)
    {
        list.push(クライアント)
    }
    
    リストを返す
}

console.log(getConnectedList())

// ['yIfhb2tw7mxgrnF6AAAA'、 'qABFaNDSYknCysbgAAAB']を返します


2

バージョン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);
    }
});

それでもこれは正しくありません


1
imはゴミのライブラリだと思い始めています。多くのタイプのデータ(json、バイナリーなど)をシームレスに転送する唯一の方法です。それ以外の場合、アーキテクチャ全体はがらくたで、1対1のチャットアプリを超えて拡張されません
Muhammad Umer

1

ソケットのmanagerプロパティからこれにアクセスできると思いますか?

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

アレイが切断されたクライアントを返すという問題があるため、3rdEdenの答えはうまくいきませんでした。Object.keys(io.manager.open).lengthは、私の経験で最も信頼できる数であることがわかりました。名前空間を使用している場合は、io.of( '/ namespace')。manager.open。
ウェスジョンソン

1

私はここで多くの良い答えを見つけ、多くは非常に便利ですが、私が必要とするものではありません。関心のあるクライアントが特定のレコードの変更をリッスンできる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");
}

これが誰かを助けることを願っています。


ソケット接続時にクライアントを部屋に参加させる場合、その「if」ステートメントを回避することは可能だと思います。
Chayemor 2015年

myObjはどこから来たのですか?どのようにしてその価値に到達しましたか?
Michael Draper

@MikeDraper myObjectは、チャネルとして機能するデータベース内のレコードです。これが解決するのは、たとえば、ユーザーが名前を更新し、接続されているすべてのクライアントが更新を取得するなど、データベースの変更が発生したときにすべてのクライアントを更新する場合です。そのため、一意(BSON)であることを前提として、そのインスタンスIDの部屋を作成します。これは私のユースケースでは非常に具体的な値なので、混乱を招いた場合は申し訳ありません。助けが必要な場合はお知らせください:)
Gus Ortiz

@JMRは、私のアプリの性質上、ソケットが2回以上サブスクライブされることがありました。そのため、チェックを追加する必要がありました。
Gus Ortiz、

1

これは、名前空間またはルームを使用していない場合、Socket.IO 1.0以降で最も簡単な方法です。

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

これはデフォルトの名前空間を見て、ソケット配列の長さを決定します。使用する必要はありません。 Object.keys()


1

バージョン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...
    }
});

何らかの理由で、ソケットIDを格納するために配列ではなくプレーンオブジェクトを使用しています。


これは機能します。io.of( '')の空の文字列は、名前空間なしで機能します。
キラリーイシュト

@KirályIstvánしばらくこれを調べていませんがof()、その場合は連鎖呼び出しを完全に削除できます。
rppc

1

クラスターモードの場合、redis-adaptorを使用

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

});

それぞれのソケットはそれ自体が部屋なので、同じものを使用してソケットが存在するかどうかを確認できます。


0

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

0

これがまだ続くかどうかはわかりません。しかし、このようなものは私が最終的に使用したものです(接続された各ソケットにセッションオブジェクトを保持します。これには、ユーザー名とその他の情報が含まれます:

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

0

プロジェクトに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ページにアクセスしてください。


0

socket.io@1.7.3

Object.Keysを使用して、接続されたソケットの配列を取得しました。次に、同じ配列内で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);

おそらく、この回答はソケットID /ユーザー名の配列を取得するのに役立ちます。


1
こんにちは-これで問題がどのように解決されるかを英語で説明していただけますか?このように、それは単なるコードのみの回答ではありません。ありがとう!
Max von Hippel 2018

0

v.10

var clients = io.nsps['/'].adapter.rooms['vse'];
/* 
'clients' will return something like:
Room {
sockets: { '3kiMNO8xwKMOtj3zAAAC': true, FUgvilj2VoJWB196AAAD: true },
length: 2 }
*/
var count = clients.length;  // 2
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.

1
「これが最良の方法」である理由と、あなたの回答が上記の多くの回答すべてにどのように追加されるかについて、何らかのコンテキストを追加できればよいでしょう。コードは何かですが、答えには説明も必要です。ご覧のとおり、この質問には他にも多くの回答があります。あなたの答えは主題に何かをもたらすに違いありません、そうでなければ、それは冗長です。
Nathan Ripert、2018年

socket.io 2.1.1 、私は得TypeError: clients.map is not a functionて、それは有望に見えますが、上記の例が何を達成するのか完全にはわかりません-私はそれがユーザー名を含むクライアントオブジェクトの配列を自動的に作成することを望んでいました:)
user1063287
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.