uNetworking / uWebSockets.js

μWebSockets for Node.js back-ends :metal:
Apache License 2.0
7.76k stars 563 forks source link

Any examples on how to do socket connection tracking? #929

Closed SiNONiMiTY closed 1 year ago

SiNONiMiTY commented 1 year ago

Title. I am looking for a way to selectively disconnect/send messages to particular WS clients. Been looking around and the examples for uWS are few.

e3dio commented 1 year ago
let id = 0;
const wsMap = new Map();

app.ws('/ws', {
  open: ws => {
    wsMap.set(ws.id = ++id, ws);
  },
  close: ws => {
    wsMap.delete(ws.id);
  }
});

wsMap.get(1).end();
wsMap.get(2).send('message');
SiNONiMiTY commented 1 year ago

So looping through maps/arrays are the solution, I see. Thank you for your quick response @e3dio. Much appreciated.

e3dio commented 1 year ago

So looping through maps/arrays are the solution,

Subscribe/publish is good for publishing messages to topic sets

SiNONiMiTY commented 1 year ago

So looping through maps/arrays are the solution,

Subscribe/publish is good for publishing messages to topic sets

Yes, I will be utilizing PubSub method. Just kinda lost on how to implement the connection tracking mechanism. Thank you for the tips :)

uNetworkingAB commented 1 year ago

wsMap.get(2).send('message');

So how do you "track" the number 2, then? It's the same exact issue, you just swapped a JS object reference for a number 2, now you still have to "track" this number 2.

So rather you just pass around the very JS object than pass around this imagined number 2. But, I don't know how you think and for me this middle map is definitely not something I would do. But then again, I don't understand JS people 😉

e3dio commented 1 year ago

More likely you assign a user id to the websocket and store it in a map, so ws by ID can be looked up. Counting up is just for this example ;)

SiNONiMiTY commented 1 year ago

wsMap.get(2).send('message');

So how do you "track" the number 2, then? It's the same exact issue, you just swapped a JS object reference for a number 2, now you still have to "track" this number 2.

So rather you just pass around the very JS object than pass around this imagined number 2. But, I don't know how you think and for me this middle map is definitely not something I would do. But then again, I don't understand JS people 😉

Typically, the number 2 here is equivalent to the ID being assigned to the socket connection.

The approach that I went here is to generate an ID for the socket during the upgrade handler

res.upgrade<TUserData>(
    {
        id: nanoid(),
        room: req.getParameter( 0 ),
        clientRole: req.getQuery( 'role' ), // Should be from JWT Payload
    },
    req.getHeader( 'sec-websocket-key' ),
    req.getHeader( 'sec-websocket-protocol' ),
    req.getHeader( 'sec-websocket-extensions' ),
    context,
)

and store it in the map like this

clientMap.set( ws.getUserData().id, ws )

then I just can access that ID for each connection via the "ws" parameter

ws.getUserData().id