socket.io traffic for other rooms - node.js

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.

Related

What is 'socket' parameters in io.on()

I'm learning Socket.io with node js ,express
In this code :
io.sockets.on('connection', function (socket) {
console.log('Log !');
});
What it's use the parameters socket in this function ?
Thanks.
The socket parameter gives you information about the connected client, such as the unique socket.id which will help you send events to that specific socket, you can see in what rooms the socket is in, you can get information about the browser and more, you can inspect it with console.log(socket) and see a lot of information that you can use

Socket.io send messges to only some users in room

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/

How to set id of a socket in WebSocket?

I'm using: https://github.com/websockets/ws as websockets.
In socket.io you could give an id to your sockets like:
io.emit('id','myText');
io.on('id',function(data){
//read data
});
In websocket on the server you can read sockets by id.
ws.on('id', function (data) {
};
You can read sockets by id on the client too.
ws.addEventListener('id', function (data) {
};
But I couldn't find how to send a socket with a specific id, I've also checked the code base. Am I missing something or is this impossible? Or are there some hacks that could achieve this?
//I want this:
ws.send('id','myText');
I'll format my comments into an answer since it appears to have explained things for you:
There is no handler for your own message names like this in webSocket:
ws.on('id', function(data) { ... });
Instead, you listen for data with this:
ws.on('message', function(data) { ... });
If you want to send a particular message name, you send that inside the data that is sent. For example, data could be an object that you had data.messageName set to whatever you want for each message.
It appears like you're trying to use a socket.io API with a webSocket. That simply doesn't work. socket.io adds a layer on top of webSocket to add things like message names. If you want to use that type of layer with a plain webSocket, you have to implement it yourself on top of a webSocket (or just use socket.io at both ends).

Socket.IO Emit is emitting to all clients

So I'm writing an app in NodeJS, and to preface my question please understand how my setup currently works:
I have Clients who connect via Socket.io to "Server X", and then my "Server X" connects via Socket.io to "Server Y", and they all send data back to each other via Socket.io.
Client <---> Server X <---> Server Y
Clients refer to users and their browsers, and then I have a node app running on both my server x and my server y.
So in the code below on my Server X, if you look at line 4 it works exactly as it should. It emits the message ONLY to the client who requested it.
io.on('connection', function(socket){
// This works just fine.
socket.emit('return_login', 'Test Message');
socket.on('login', function(data){
// This line correctly sends the data to Server Y
server_y.emit('login', data);
});
server_y.on('return_login', function(data){
// This emits to all connected clients???
socket.emit('return_login', data);
});
});
Now my problem is when "Server Y" emits return_login to server x, what I want to happen is for server x to take the value emitted by server y and just send it back to the original client, or web browser. But for some reason that line emits to ALL connected clients.
I have a laptop, this computer and my phone all testing this and every time that emit happens it sends to EVERYONE.
If someone could please help me with this I would greatly appreciate it. If I need to post more code please let me know.
I am not sure about your code. But I usually use room to emit to an user and callback function of socket. This is my solution using callback instead of return_login event
io.on('connection', function(socket){
socket.on('login', function(data, callback){
// Using callback instead of return_login event
server_y.emit('login', data, function(responseData){
// put this socket to room as name = user_id
socket.join(responseData.user_id);
// return result by callback
callback(responseData)
});
});
});
// emit to exactly user_id with return_login event if you want
io.to(user_id).emit('return_login', {key: 'ok'})
It is sending to all clients because you have installed a separate listener for each socket for the return_login message. So, when one client logs in and the return_login message is sent back to your server, you have a separate listener for every single socket that sees that message and forwards it to that socket. In this way, it gets sent to every connected socket.
One way to fix that is to make sure that the return_login message is only sent to the socket that it belongs to. If you can send a socket.id with that message and have that server echo that id back as part of the response, then you can check that when you receive the message to make sure you only send it to the socket that it belongs to.
This is one of the issues with a pure message-based system. You are trying to do a request/response where only the requester sees the response, but socket.io isn't a request/response system. A response is sent to all listeners of that particular message and since you have a listener for that message for every single socket that is connected, every single socket is seeing it and then forwarding it on to it's client.
So, with a corresponding modification to the other server to echo back the id value, you could do this:
io.on('connection', function(socket){
// This works just fine.
socket.emit('return_login', 'Test Message');
socket.on('login', function(data){
// add our id so we can identify our response back
data.id = socket.id;
server_y.emit('login', data);
});
let fn = function(data) {
// check to see if this message is destined for this socket
if (data.id === socket.id) {
// make data copy with id value removed so
// we don't send that to the client
let tempData = Object.assign({}, data);
tempData.delete(id);
socket.emit('return_login', tempData);
// we're done with this listener so remove it
server_y.removeListener('return_login', fn);
}
});
server_y.on('return_login', fn);
});
It might be tempting to just remove your listener for the return_login message after you receive it, but that causes a race condition if two clients happen to both be in the process of logging in at the same time and thus both have listeners at the same time, then the first message would be received by both listeners.

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

Resources