Socket.io send messges to only some users in room - node.js

I want to send message in a room using socket.io but i some cases i want to skip some users in room so how can i do that.
Currently i am using below code to send message in group
io.on('connection', function (socket) {
sockets[socket.handshake.query.id]=socket;
console.log("user_connect",socket.handshake.query );
if(socket.handshake.query.user_type=="DRIVER"){
socket.join('orderPool');
}
socket.join('USER_'+socket.handshake.query.id);
socket.on('disconnect', function () {
delete sockets[socket.handshake.query.id];
console.log('user disconnected', socket.handshake.query.id);
});
});
io.sockets.in("ROOMNAME").emit("POOL_EVENT_RECIEVED", data);

One solution is to simultaneously keep another room "<room name>-selected users" with only selected users you want to send the messages. Don't add to this room the users you want to skip.
So, when you send messages to this room, users who weren't added to this room won't receive those messages.

sometimes io disconnected and try to reconnect again but I think it's not your problem.
Note that you can emit to rooms that exists in particular namespace. if you use default namespace '/' so try it:
io.of('/').in("ROOMNAME").emit("POOL_EVENT_RECIEVED", data);
also you can read socket.io emit cheatsheet: https://socket.io/docs/emit-cheatsheet/

Related

How does socket.to(username).emit('eventName',{}) work?

Can someone please explain how does socket.to(username).emit('eventName',{}) work? Basically I want to know how it identifies the 'username' is logged in or not.
socket.to(room).emit(...) will emit messages to all the users that joined room using: socket.join(room).
By default, each socket joins a room identified by the socket id, that's why, you can also do: socket.to(socketId)
Without knowing your logic, username room will be empty if the user isn't logged in, and it will have the logged user if the user is online. Socket.io doesn't really know if the user is online or not, it only knows that there is an user in that room.
io.on('connection', (socket) => {
console.log('New user connected');
const username = getUsernameSomehow(); // logged user, ip, cookie, or whatever you like
// When the user is online, it will join to
// a room named after his username
socket.join(username);
socket.on('send', (message) => {
console.log(message);
// Now you can send a message by only knowing the username
socket.to(message.target).emit('message', message.text);
});
});
If you don't join the user to username room, your code will never work.
First of all, it's not a username, it's a socket.id value or a room name that works in:
socket.to(roomname).emit(...)
The way it works is very socket that connects to your server is given a socket.id value and then that value is then added to a data structure the socket.io server keeps. Any times a socket disconnects that socket.id is removed from the data structure.
So, when you do this:
socket.to(roomname).emit(...)
socket.io looks up the roomname you pass in its internal data structure. If it's there, then it can get the socket from that data structure and can then send to it.
Because socket.io also automatically creates a room with the name of the socket.id that every socket is given, you can also do:
socket.to(socketID).emit(...)
And, using the same mechanism above, it will look for a room named with the socketID and because there is matching room for every socket that is connected, it will find that room and then send to the socket with that socketID.
socket.io itself does not have any notion of username. You would have to add that level of functionality yourself or get it from a cookie (if there's already a login cookie) when the socket.io connection is first established.

socket.io: why doesn't this broadcast statement work?

I'm trying to use broadcast statement to send messages to specific user.However, when I'm starting with self-sending messages using the following statement, it doesn't work. The client side cannot receive the message. So what's wrong with this statement?
io.on('connection', function(socket) {
socket.on('message', function(msg) {
socket.broadcast.to(socket.id).emit('message', msg);
});
});
(purpose of this code: the client side send a piece of message named 'message', the server receive the message and send back to the same client)
socket.broadcast.to broadcasts to all sockets in the given room, except to the socket on which it was called while io.sockets.in broadcasts to all sockets in the given room. (cited from Daniel Baulig's answer to another question:)Socket.io rooms difference between broadcast.to and sockets.in

socket.io traffic for other rooms

Why do i see traffic for other rooms in (chrome/network).
Node.js and socket.io 0.9.16
Simplified setup
//sockets-server
socket.on('subscribeToSome', function (data) {
joinToRoom(socket, data);
console.log("joining" + data.room);
});
//client
socket.emit(subscribeToSome, {room: room, data: dataToSubscribe});
socket.on(room, function(data){
console.log(data);
});
//route -server
global.io.sockets.emit("room1", {aa:"ads"}
Everything works but i can see traffic for other rooms in (chrome/network) even doe in not member of it. (data is not visible in the callback only in network/Websockets)
How come? And how do i solve it.
Thanks. //Karl
From what i can see from your code you're not emitting your message to a room but you use an eventname for the message. As shown in the documentation, emit takes a String as the first parameter, giving that message a name which your callbacks are hooked to.
Emitting to a room would look like the following:
global.io.sockets.to("room1").emit("message", {aa:"ads"}
You also need to join your socket into that room for it to receive the respective messages.
See http://socket.io/docs/rooms-and-namespaces/ for more information on that topic.

how to get number of socket connections using socket.io

Is there a way to get the number of connections in socket.io?
I want to display a message on my site that says "x users connected right now"
Basically if I did a socket.broadcast I want to count how many connections that would go to.
You can use
io.sockets.clients().length
Basically io.sockets.clients() returns Socket instances of all clients. If you're using rooms then you should better use
io.sockets.clients('room').length
because it returns socket instances of all clients in a particular room
Using this code Server site
var noOfUser=[];
socket.on('someEventFromClient',function(data){
//User name must unique
socket.username=data.username;
noOfUser.push(data.username);
//Now you can emit no of user to client are any where
console.log('NO of user:'+noOfUser.length);
});
socket.on('disconnect',function(){
for(var i=0;i<noOfUser;i++)
{
if(noOfUser[i]==socket.username)
{
noOfUser.splice(i,1);
}
//Now you can emit no of user to client are any where
console.log('NO of user:'+noOfUser.length);
}
});
Client side:
when user connect socket server emit this event
socket.emit('someEventFromCLient',{username:'someuniqueID'});

List of connected clients username using socket io

I've made a chat client with different chat rooms in NodeJS, socketIO and Express. I am trying to display an updated list over connected users for each room.
Is there a way to connect a username to an object so I could see all the usernames when I do:
var users = io.sockets.clients('room')
and then do something like this:
users[0].username
In what other ways can I do this?
Solved:
This is sort of a duplicate, but the solution is not written out very clearly anywhere so I'd thought I write it down here. This is the solution of the post by Andy Hin which was answered by mak. And also the comments in this post.
Just to make things a bit clearer. If you want to store anything on a socket object you can do this:
socket.set('nickname', 'Guest');
sockets also has a get method, so if you want all of the users do:
for (var socketId in io.sockets.sockets) {
io.sockets.sockets[socketId].get('nickname', function(err, nickname) {
console.log(nickname);
});
}
As alessioalex pointed out, the API might change and it is safer to keep track of user by yourself. You can do so this by using the socket id on disconnect.
io.sockets.on('connection', function (socket) {
socket.on('disconnect', function() {
console.log(socket.id + ' disconnected');
//remove user from db
}
});
There are similar questions that will help you with this:
Socket.IO - how do I get a list of connected sockets/clients?
Create a list of Connected Clients using socket.io
My advice is to keep track yourself of the list of connected clients, because you never know when the internal API of Socket.IO may change. So on each connect add the client to an array (or to the database) and on each disconnect remove him.
In socket.io#2.3.0 you can use:
Object.keys(io.sockets).forEach((socketId) => {
const socket = io.sockets[socketId];
})

Resources