简体   繁体   中英

Socket.io - io.to.emit emits to all connected users

I have a MEAN app setup with npm socket.io with expressjs and btford.socket-io on the client.

angular.module('myApp',['btford.socket-io'])
    .factory('socket',function(socketFactory){
       return socketFactory();
    }
).controller('myAppCtrl',['$scope','socket',
    function(a,b){
            b.on('test',function(data){
            console.log(data);
        });
    } 
]);

Here's the node-express setup:

var app = express(),
    server = app.listen(3000);

var socket = require('socket.io'),
    io = socket.listen(server);

require('/config/routes/index.js')(app,io);
require('/config/routes/test.js')(app,io);

Routes : (config/routes/index.js)

module.exports = function(app,io){
    app.get('/',function(req,res){
        io.on('connection',function(socket){
            socket.join(req.session._id);
        });
        res.render('index');
    });
};

config/routes/test.js

module.exports = function(app,io){
    app.get('/route1',function(req,res){
        io.to(req.session._id).emit('test',{
            data : 'Works'
        });
        res.render('route1');
    });  
};

A) Whenever the user goes to route1, the emit event is being fired and sent to all the users.

B) Is there a better approach to avoid using unique room for each user? This is not a chat application but rather implements push notifications

You need to think of the connection from socket.io separately from a request. They are NOT tied together the way that you think they are. Your connection listener is for any connection not just a connection related to a given request... what you are trying to do simply will not work that way.

Imagine that your socket.io portions of your project are completely separate from the http requests in the web/express portions of your application. This is how you should think of passing messages.

Also worth consideration is that if you are using cluster or similar scaling methods, your default socket.io setup in one instance doesn't communicate with other instances.

You have a couple major misunderstandings about how sockets and requests work. They are very separate operations and are not connected the way you appear to think they are. I will try to explain the problems with your code.

In this block of code:

module.exports = function(app,io){
    app.get('/',function(req,res){
        io.on('connection',function(socket){
            socket.join(req.session._id);
        });
        res.render('index');
    });
};

You are processing the / page request and EVERY time that request is hit, you add yet another event handler for io.on('connection', ...) , thus you could have many of those.

Further, if the connection event happens BEFORE the user hits the / page, then you will miss it entirely and that socket will not be placed into the proper chat room.


Then, in this block of code:

module.exports = function(app,io){
    app.get('/route1',function(req,res){
        io.to(req.session._id).emit('test',{
            data : 'Works'
        });
        res.render('route1');
    });  
};

io.to() takes a string that is the name of a chat room. So, this will send a message to every socket that is in the req.session._id chat room. For this to work, you'd have to make absolutely sure that req.session._id was completely unique to this user and that the desired user had already joined a chat room by this name. This could work, but it depends upon those specific things being correct.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM