node.jswebsocketws

how do I keep track of clients connecting and disconnecting in Node.js WebSocket Server?


How do I keep track of users connecting and disconnecting from a WebSocket Server in Node.JS using the 'ws' module?

I need to dynamically add and remove the WebSockets to an array, so if I needed to send something to a specific WebSocket, I could just do clients.send('blah blah blah'),

Is there any way to do this? I have tried but failed. Here is what I have tried,

This is my 'clients module'

clients = [];

function addClient(ws, wss, WebSocket) {
    clients.push(ws);
    console.log("Client Connect: " + clients.indexOf(ws) + ". " + clients.length + " Online")

    ws.on('message', function incoming(data, isBinary) {
        wss.clients.forEach(function each(client) {
            if(client != ws && client.readyState == WebSocket.OPEN) {
                const msg = isBinary ? data : data.toString();
                client.send(msg);
            }
        })
    })
    ws.onclose = function() {
        removeClient(ws);
    }
}

function removeClient(ws) {
    let indx = clients.indexOf(ws)
    clients = clients.splice(clients.indexOf(ws), 1)
    console.log("Client Disconnect: " + indx + ". " + clients.length + " Online")
}


module.exports = {
    clients, addClient, removeClient
}

addClient is called whenever the WebSocket Server recieves 'connection' The three arguments are:

This code works somewhat-normally, but breaks easily. If someone connects, the list adds the websocket to the clients list. If someone disconnects, it sometimes removes it as intended, and other times, it just doesn't, and there is a 'ghost websocket'

I can't seem to find a good way to achieve this, so I'm just asking for help.

When a client connects, add it to the clients list so I can send stuff to it by index.

When a client disconnects, remove it from the list.


Solution

  • After more research, I've learned that you can assign any attribute or property to a WebSocket that will stay throughout the entire lifecycle. I have simply added a counter that never goes down and increases when someone connects, and set an id attribute to that counter. I then use an array.filter to filter out the client with the id that the disconnecting WebSocket had.

    Here is the code:

    clients = [];
    aid = 0;
    
    function addClient(ws, wss, WebSocket) {
        ws.userid = aid;
        aid+=1;
        clients.push(ws)
    
        console.log("Client Connect: " + ws.userid + ". " + clients.length + " Online")
    
        ws.on('message', function incoming(data, isBinary) {
            wss.clients.forEach(function each(client) {
                if(client != ws && client.readyState == WebSocket.OPEN) {
                    const msg = isBinary ? data : data.toString();
                    client.send(msg);
                }
            })
        })
    
        ws.onclose = function() {
            removeClient(ws);
        }
    }
    
    function removeClient(ws) {
        clients = clients.filter((check) => {
            return check.userid != ws.userid
        })
        console.log("Client Disconnect: " + ws.userid + ". " + clients.length + " Online")
    }
    
    
    module.exports = {
        clients, addClient, removeClient
    }