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 เป็น hash object แบบง่าย id => socket
mak

1
ฉันสังเกตเห็นว่า แต่มันทำหน้าที่แปลก (ดูเหมือนจะไม่เหมือนวัตถุซ็อกเก็ตมาตรฐาน) ตัวอย่างเช่นฉันลอง: pastebin.com/fxuzVckSแต่มันบอกว่าวัตถุซ็อกเก็ตไม่ได้มีวิธีการ 'รับ'
Andy Hin

3
socketis id 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


ปรับปรุง 25 มี.ค. 06

จาก 1.x ขึ้นไปโปรดอ้างอิงลิงค์นี้: รับจำนวนคนในห้องแชทใน socket.io


3
ฉันคิดว่าพวกเขาได้ทิ้งวิธีการของลูกค้าใน 1.0 ... เพียงตรวจสอบที่ออกในขณะนี้ ...
markyzm

7
พวกเขาลดลงเกือบทุกอย่างใน 1.0 เนื่องจากเป็นการเขียนใหม่ที่สมบูรณ์ แต่ในฐานะที่เป็น 1.0 ได้ถูกปล่อยออกมาหลายปี ใน 1.0 คุณต้องใช้connectedวัตถุของเนมสเปซ
3rdEden

6
@ 3rdEden ไวยากรณ์สำหรับการใช้ออบเจ็กต์ที่เชื่อมต่อของเนมสเปซคืออะไร var clients = io.sockets.connected();เห็นได้ชัดว่าใช้งานไม่ได้ ขอบคุณ
Kaya Toast

5
ตั้งแต่ 1.x ขึ้นไป: stackoverflow.com/questions/9352549/…
Musa Haidari

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 สำหรับการไม่มี namespace ที่จะกลายเป็น

// 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 สำหรับnamespaceกลายเป็น:

// 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
ขอบคุณสำหรับสิ่งนี้. ฉันประหลาดใจที่พวกเขาลบฟังก์ชันการทำงานนี้ออก
Tyler Scott

1
@TylerScott ฉันด้วยเช่นกันโดยเฉพาะอย่างยิ่งเนื่องจากสิ่งนี้ไม่ได้กล่าวถึงในคู่มือการย้ายถิ่นของพวกเขา (ยกเว้นกรณีที่ฉันขาดอะไรไป) socket.io/docs/migrating-from-0-9
nha

@nha นี่ใช้ไม่ได้กับฉัน แต่ส่งคืนอาร์เรย์ของจำนวนเต็มเช่น 0, 1 และ 2 เป็นต้นไปแทนที่จะเป็นอาร์เรย์ของซ็อกเก็ต ความคิดใด ๆ
ThePixelPony

สำหรับหลาย ๆ โหนดล่ะ เพราะฉันใช้หลายโหนดกับร้าน 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
Fábio 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 เพื่อความง่าย คุณรู้หรือไม่ว่ามีความแตกต่างระหว่างวิธีนี้กับคำตอบของ Joseph Dykstra ไหม? (Object.keys(io.engine.clients)
cyclingLinguist

4
สิ่งนี้ใช้ไม่ได้กับ v1.4.5 ยังคงหาทางแก้ปัญหาอยู่
Nuno Furtado

คุณเจอหรือไม่ \
ocram

2
TypeError: io.sockets.sockets.map ไม่ได้เป็นฟังก์ชั่น
KirályIstván

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 กับ namespace วิธีการข้างต้นจะแตกเนื่องจาก 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 คุณระบุ namespace / room / node ที่คุณกำลังสอบถาม

เช่นเดียวกับการออกอากาศค่าเริ่มต้นคือไคลเอนต์ทั้งหมดจากเนมสเปซเริ่มต้น ('/'):

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)- มันน่าจะเป็นวัตถุที่มูลค่าทรัพย์สินแต่ละคนเป็น "ซ็อกเก็ตวัตถุ" ซึ่งมีคุณสมบัติเหล่านี้nsp, server, adaptor, id(สตริง) client, conn, rooms, acks, connected, disconnected, handshake, fns, flags, _rooms, _events, _eventsCountและในที่สุดusernameซึ่งเป็นคุณสมบัติที่กำหนดเองฉันจะเพิ่มให้กับแต่ละซ็อกเก็ตในการเชื่อมต่อ
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");
    });    
});

เมื่อวันที่โปรดลบชื่อเล่นจากdisconnectio.sockets.sockets


จุดประสงค์ของ 'client.on' คืออะไร? คุณสามารถใช้รหัสของคุณเช่นนี้ (ยอมรับเฉพาะข้อมูลจาก 1 ซ็อกเก็ต) หรือไม่: io.sockets.sockets [sock_id] .on ('newmessage', ฟังก์ชัน (ข้อมูล) {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

5

สำหรับทุกคนที่ต้องการเพียง COUNT ของลูกค้าที่เชื่อมต่อฉันเชื่อว่ามันจะทำ:

io.sockets.manager.server.connections


ไม่นับลูกค้าที่เชื่อมต่อนับทดสอบ (อีกเล็กน้อย)
mrzmyr

5
เพื่อให้การนับถูกต้องio.sockets.clients().length
Ivo

2
ขณะนี้ทั้งสองio.sockets.manager.server.connectionsและio.sockets.clients().lengthไม่ทำงาน นี้ทำงานสำหรับฉัน - สำหรับการนับเท่านั้น - io.engine.clientsCountและรายชื่อของลูกค้า io.engine.clientsCount- เนื่องจากมันยังคงอยู่แบบนี้มานานกว่า 3 ปี ดูเหมือนว่าวิธีที่เชื่อถือได้ในการรับข้อมูลการเชื่อมต่อ (ตามคำตอบของ Joseph Dykstra)
Aswin Ramakrishnan

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

ฉันยืนยันว่ามันใช้งานได้กับsocket.io
Sébastien

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

คุณนึกภาพไม่ออกว่าปวดมากแค่ไหนที่คุณได้ช่วยฉัน
nicholaswmin

แต่เวอร์ชั่น 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 ()
{
    ให้รายการ = []
    
    สำหรับ (ให้ไคลเอ็นต์ใน 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);
    }
});

ยังคงนี้ไม่รู้สึกขวาเพราะฉันมีความรู้สึกนี้เสมอกับซ็อกเก็ต Io อย่างใด


1
ฉันเริ่มคิดว่ามันเป็นห้องสมุดขยะ สิ่งเดียวที่ทำให้การถ่ายโอนข้อมูลหลายประเภทเป็นไปอย่างราบรื่น (json, binary, etc) มิฉะนั้นสถาปัตยกรรมทั้งหมดเป็นเรื่องไร้สาระและไม่ขยายไปเกิน 1 ใน 1 แอพแชท
Muhammad Umer

1

ฉันเชื่อว่าคุณสามารถเข้าถึงสิ่งนี้ได้จากคุณสมบัติของผู้จัดการซ็อกเก็ต?

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

คำตอบที่ 3 ของฉันไม่ได้ผลสำหรับฉันเนื่องจากมีปัญหากับอาเรย์ที่ส่งคืนลูกค้าที่ถูกตัดการเชื่อมต่อซึ่งส่งผลให้เกิดการนับ Object.keys (io.manager.open) ความยาวกลายเป็นความน่าเชื่อถือมากที่สุดในประสบการณ์ของฉัน io.of ('/ namespace'). manager.open หากคุณใช้เนมสเปซ
Wes Johnson

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

myObj มาจากไหน คุณมาถึงคุณค่านั้นได้อย่างไร
Michael Draper

@MikeDraper myObject เป็นบันทึกในฐานข้อมูลที่ทำหน้าที่เป็นช่องทาง สิ่งนี้แก้ไขได้ในกรณีที่คุณต้องการให้ไคลเอนต์ทั้งหมดของคุณได้รับการอัปเดตทุกครั้งที่มีการเปลี่ยนแปลงฐานข้อมูลเกิดขึ้นตัวอย่างเช่นผู้ใช้อัพเดตชื่อและลูกค้าที่เชื่อมต่อทั้งหมดจะได้รับการอัปเดต ดังนั้นฉันจึงสร้างห้องสำหรับรหัสอินสแตนซ์นั้นเนื่องจากมันไม่ซ้ำกัน (BSON) มันเป็นค่าที่เฉพาะเจาะจงมากสำหรับกรณีการใช้งานของฉันดังนั้นฉันขอโทษถ้าฉันทำให้เกิดความสับสน แจ้งให้เราทราบหากคุณต้องการความช่วยเหลือ :)
Gus Ortiz

@JMR เนื่องจากลักษณะของแอปของฉันมันเกิดขึ้นว่าซ็อกเก็ตได้สมัครเป็นสมาชิกมากกว่าหนึ่งครั้งนั่นคือสาเหตุที่ฉันต้องเพิ่มเช็คนั้น
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

@ KirályIstvánฉันยังไม่ได้ตรวจสอบในขณะนี้ แต่ฉันคิดว่าคุณสามารถลบof()สายที่ถูกล่ามโซ่ได้ในกรณีนี้
rppc

1

สำหรับโหมดคลัสเตอร์โดยใช้ redis-adapter

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

กรุณาเยี่ยมชมหน้าGithub socket.io-redisสำหรับรายละเอียดเพิ่มเติม


0

socket.io@1.7.3

ฉันใช้ Object.Keys เพื่อเชื่อมต่ออาร์เรย์ของซ็อกเก็ต จากนั้นในอาร์เรย์เดียวกันซ้ำกับฟังก์ชั่นแผนที่เพื่อสร้างอาร์เรย์ของวัตถุใหม่

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

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

เมื่อsocket.io 2.1.1 ฉันได้รับTypeError: clients.map is not a functionและถึงแม้ว่ามันจะดูดี แต่ฉันก็ไม่แน่ใจว่าตัวอย่างข้างต้นจะประสบความสำเร็จได้อย่างไร - ฉันหวังว่ามันจะสร้างอาร์เรย์ของออบเจ็กต์ไคลเอ็นต์ที่มีชื่อผู้ใช้โดยอัตโนมัติ :)
user1063287
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.