Socket IO detect if user leaves a room - node.js

I want to listen for the event in which a user leaves a room. From what I've researched, socket.rooms apparently contains the rooms that a socket is in. However, when I listen for the disconnect event from a socket, apparently the socket left the room prior to disconnect. Therefore, socket.rooms will yield an empty object after the disconnect event. I need to listen specifically for the event in which a user leaves a room, not the socket disconnect event, since I have an array of room objects and wish to delete the user from the room when they leave.

A user cannot leave a room without your server removing them from the room or when the user disconnects. Clients cannot leave a room on their own. So, to know when a user leaves a room, you just need to hook into your own code that removes them from a room and also listen for the disconnect event.
Other than a disconnect, the only other way a user can leave a room is if your own code removes them from a room so you can just hook into that specific function and trigger the update of your own data structures when your own code removes them from the chat room.
For the disconnect event, if you are maintaining your own room data structures, then you can just remove a given socket from any room that you find it in when you get the disconnect event (e.g. search each room and remove it from any room that you find that socket in).

Related

Should socket.io join room or listen on unique ID to receive message from server

I working on real-time chat project. Multi user can chat and receive chat in room
Every room have an unique ID.
when user join a room, which case should I use?
Case 1 :
-User emit an event "join" with data is room ID to server, SocketIO server let user join to room with name is ID. Then when user chatting, user emit an event "chat" with chat data to server and server emit that chat to all user in that room by io.in(roomID).emit("chat",chatData)
Case 2 :
When user join room, user can listen an event have name is roomID like
socket.on(roomID, handleChatDataFunc)
When user chat, it's working like case 1, user emit an event "chat" with chat data to server, but now server will broadcast an event have name is roomID like
io.emit(roomID, chat Data);
So all user listen an event name roomID will receive chatData
All the chat will be public so I don't need to authenticated user
The reason for a room is so that the server can emit to ONLY those users. A client pre-declares to the server which things they are interested in so the server knows what to send them and what not to send them.
Your proposal to just have clients listen to msg names that they want means that your server has to send ALL data to ALL users, whether they are listening or not - whether they want that info or not. That's inefficient (sending data to clients that they don't want or need) and completely impractical with large numbers of clients.

Socket io creates rooms when a socket connects

Every time a socket joins a room is created in my application. Is this normal behavior?
I am not creating these rooms, as you can tell the room name is called the ID of the socket, which I find weird. Is this normal behavior?
This is normal behavior. Socket.io creates a room with the name of the connection's socket.id and automatically places only that socket in the room. This allows you to do things like:
io.to(someSocketId).emit(...)
because the socket.id is also a room name. Since socket.id values are unique and random and because all room participation is controlled by the server only, it's really just a server housekeeping thing that doesn't affect anything else.
If you have some reason to want to be able to discern which rooms are ones you created and which ones are the automatic socket.id form, you can put a unique prefix on the ones that you create such as an underscore and then you can tell which ones are yours and which ones are created by the system.
When the connection disconnects, that room will also go away.

How to find the room in Which the socket is in?

I want to know the room in Which the socket is in ? I want to broadcast to the other sockets in the room during the disconnect event
If you're only ever going to have a socket in one room at a time, you can just set that room as a property on the socket object when you join it to the room. socket.currentRoom = room. Then, upon disconnect, you can just access socket.currentRoom to see what room you had it in.
It is possible to dive into internal data structures to find out what rooms a socket is in, but if you're just using one room, then the socket.currentRoom is probably easiest.

socket.io room authorisation

I have a use case of socket.io where, within an individual namespace, a client can connect to several rooms. A user needs to authenticate on a per-room basis (because they may not be allowed to access those data streams).
Obviously I can check the authorisation on connection to the namespace using a middleware function and some auth data, but unless those rooms are already in socket.rooms when the connection is initiated, I do not know how to check, when a socket joins a room, whether or not it is authorised and subsequently force it to leave the room if it is not authorised.
Is there a join event or equivalent way of doing this? Like the connection event for a namespace but for a room.
EDIT
Having read through the source for socket.io, it appears that no events are triggered when a socket joins a room, but I might have misunderstood something: on reading the source of socket.io-client, joining rooms isn't inherent in the system, suggesting that this is only something that can be triggered on the server side. In that case, I'm assuming I have to manage the client's joining of rooms myself? If this is true, then I can just have something like:
socket.on('join', function(data) { ... });
so that when a socket wants to listen to a particular data stream, it just emits a "join" event, with some data on which room it wants to join, and I handle the whole thing on the server?
Joining a room can only be done on the server. The client typically sends an application-specific message to the server that indicates to your app that they want to join a specific room and then the server carries out that operation on the user's behalf if the request is valid.
So, all you have to do is route all your code on the server that could join a room through one particular function that can do whatever authentication you want to do. For example, you could simply create a function that was the only way your server code would ever put a socket into a room:
function joinAuth(socket, room) {
// can do anything you want here before actually joining the room
}

Keep socket.io room alive when all clients disconnect?

I have a multiplayer game with game rooms built in Node.js and socket.io. There are 4 players per game room and rooms are created when the first player joins. When I send data to a client connected to the room, I always perform the following check to make sure they're still in the room (sock_id is the socket ID of the client):
if(io.sockets.manager.rooms['/' + room].indexOf(sock_id) > -1){
...
}
If a player leaves the room, he is replaced by a robot player. However, I'm running into a problem when all 4 players disconnect. The room is automatically destroyed, and the above check throws an error cannot call method indexOf of undefined, indicating the room doesn't exist. One way to counter this is to add a check to make sure the room exists to every such check on the Node server (and there are quite a few).
But, I was wondering if it's possible to keep the room alive in some way even when all clients disconnect. I could then destroy the room when the game in question ends, and the problem is solved.

Resources