socket.io - how to broadcast messages on a namespace?
According to socket.io examples:
To broadcast, simply add a
broadcast
flag toemit
andsend
method calls. Broadcasting means sending a message to everyone else except for the socket that starts it.
var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) {
socket.broadcast.emit('user connected');
});
I tried to combine this with the new socket.io namsepace feature, so I got this:
var chat = ioserver.of('/chat');
chat.on('connection', function (socket) {
console.log('chat connection');
socket.on('message', function (msg) {
console.log(msg);
chat.send(msg);
});
});
This works fine, everyone on the chat channel (and no other channels) gets the message. But the sender also gets it. So I tried to do the following:
chat.on('connection', function (socket) {
console.log('chat connection');
socket.on('message', function (msg) {
console.log(msg);
chat.broadcast.send(msg);
});
});
and got an Exception: 'Cannot call method 'send' of undefined.' Ok, so I thought, that broadcast is the feature of a single socket (it feels a bit weird though - how a single socket can brodacast to all other...). So I tried:
chat.on('connection', function (socket) {
console.log('chat connection');
socket.on('message', function (msg) {
console.log(msg);
socket.broadcast.send(msg);
});
});
but now it was even worse - no one received the message, not even the sender. Anyway, it was what I logically expected - one socket cannot broadcast something through itself. And no exceptions this time, so broadcast is defined for the socket.
If I do:
chat.on('connection', function (socket) {
console.log('chat connection');
socket.on('message', function (msg) {
console.log(msg);
socket.send(msg);
});
});
then only the original sender gets the message, and that is again pretty logical - I used the 'send' of the client-related socket.
So the question is: what is the correct way to use the broadcast feature?
Maybe the developer of socket.io made a mistake and added the broadcast feature to the wrong object (as I understand, it should be the feature of the namespace but now it is defined only for the socket)?
Solution 1:
Seems I was able to solve this for myself after opening a bounty. Sorry about that.
Anyway, see if this helps:
chat.on('connection', function (socket) {
socket.on('message', function (msg) {
socket.emit(msg); // Send message to sender
socket.broadcast.emit(msg); // Send message to everyone BUT sender
});
});
However, you could save some bandwidth and create a more snappy experience for users if you don't resend it to the sender. Just add their messages directly to the chat log, and optionally use use only self-emit to confirm it was received without issue.
Solution 2:
You solution works if you are working in an evented environment where messages from the client trigger a response to all others, but not if you want the server to sent messages to all clients.
You can do this using io.sockets.emit
:
var io = require('socket.io').listen(80);
io.sockets.emit('message', { message: "Hello everyone!" });
However the documentation isn't clear for how to do this to a specific namespace. io.sockets
is just a shortcut to io.of('')
, as such you can broadcast to everyone on a namespace by calling io.of('/namespace').emit
:
var io = require('socket.io').listen(80);
io.of('/admins').emit('message', { message: "Hello admins!" });
Solution 3:
var customNS = ioserver.of('/chat');
customNS.on('connection', function (socket) {
socket.on('message', function (msg) {
// Send message to sender
socket.emit(msg);
// Send message to everyone on customNS INCLUDING sender
customNS.emit(msg);
// Send message to everyone on customNS BUT sender
socket.broadcast.emit(msg);
// Send message to everyone on ROOM chanel of customNS INCLUDING sender
customNS.in('ROOM').emit(msg);
// Send message to everyone on ROOM chanel of customNS BUT sender
socket.broadcast.in('ROOM').emit(msg);
});
});
also check this answer Send response to all clients except sender (Socket.io)
Solution 4:
Maybe this will help someone
socket.broadcast.to('room1').emit('updatechat', 'SERVER', username + ' has connected to this room');
see
Nodejs and Socketio Multiroom Chat Tutorial