I have a Node.js web server that runs a socket server on top, which was created using Socket.io. Basically, this works.
What I now want to achieve is that the clients that connect are clustered in groups. So there might be some clients which make up group A and some other clients which make up group B. They shall select to which group they belong by adressing a specific URL, either localhost:3000/A
or localhost:3000/B
.
In Socket.io I now want to send messages to all clients in group A or to all clients in group B or to all clients, without looking at their group.
It's basically like having a chat with rooms, and you have either messages for all clients within a specific room, or for any client, no matter what room he is in.
What is the best way to design such a system using Socket.io?
I have been trying using namespace so far, which basically works for creating groups A and B, but then I lose the ability to send messages to all clients, no matter what room they are in. At least I don't know how to do this.
How should I model this? What are the right terms I should look for?
UPDATE: According to the answer of @sdedelbrock I could use namespace or rooms:
io.sockets
is a shortcut to io.of('')
, which of course does not match the namespace any longer.To cut it short: Why are there two concepts for the same (?) idea?
You could be using rooms so you would do the following to emit to everybody in a room
io.sockets.in('a').emit('inA', 'foo')
Then to emit to everybody you can use
io.sockets.emit('everyone','bar');
You can also use namespaces as well:
io.of('/b').emit('inB', 'buzz');
To emit to everyone except the user that triggered you would use:
io.sockets.broadcast.emit("hello");
[edit] Here is a more detailed answer:
The idea behind name-spacing is that it is handled separately from the other namespaces (even global). Think of it as if it was an entirely new socket.io instance, you can run new handshakes, fresh events, authorizations, etc without the different namespaces interfering with each other.
This would be useful for say /chat
and /tracking
where the connection event would have very different logic
Socket.io does all the work for you as if it is two separate instances, but still limits the information to one connection, which is pretty smart.
There might be a workaround in which you can broadcast to all the namespaces (example below). However in short you shouldn't be doing this, you should be using rooms.
for (var nameSpace in io.sockets.manager.namespaces){
io.of(nameSpace).emit("messageToAll", message);
}
This is a template application you can use (works for 9.16; not tested on 1.x but it should work):
var namespaces = [
io.of('/ns1'),
io.of('/ns2'),
io.of('/ns3')
];
for (i in namespaces) {
namespaces[i].on('connection',handleConnection(namespaces[i]));
}
function handleConnection(ns) {
return function (socket){ //connection
console.log("connected ");
socket.on('setUsername',setUsernameCallback(socket,ns));
socket.on('disconnect', disconnectCallback(socket,ns));
socket.on('messageChat',messageChatCallback(socket,ns));
socket.on('createJoinRoom',createJoinRoomCallback(socket,ns));
};
}
function disconnectCallback(socket,ns) {
return function(msg){
console.log("Disconnected ");
socket.broadcast.send("It works!");
};
}
You could write other handles by yourself :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With