1

I'm trying to learn node.js cluster with socket.io to create a chat application... the problem is that I can't seem to get things working.

i've been trying to go through all the tutorials including the one that I get from this http://stackoverflow.com/questions/18310635/scaling-socket-io-to-multiple-node-js-processes-using-cluster/18650183#18650183

when I try to open two browsers, the messages does not go to the other browser.

here's the code that i got

var express = require('express'),
    cluster = require('cluster'),
    net = require('net'),
    socketio = require('socket.io'),
    socket_redis = require('socket.io-redis');

var port = 3000,
    num_processes = require('os').cpus().length;

if (cluster.isMaster) {
    // This stores our workers. We need to keep them to be able to reference
    // them based on source IP address. It's also useful for auto-restart,
    // for example.
    var workers = [];

    // Helper function for spawning worker at index 'i'.
    var spawn = function(i) {
        workers[i] = cluster.fork();

        // Optional: Restart worker on exit
        workers[i].on('exit', function(code, signal) {
            console.log('respawning worker', i);
            spawn(i);
        });
    };

    // Spawn workers.
    for (var i = 0; i < num_processes; i++) {
        spawn(i);
    }

    // Helper function for getting a worker index based on IP address.
    // This is a hot path so it should be really fast. The way it works
    // is by converting the IP address to a number by removing non numeric
  // characters, then compressing it to the number of slots we have.
    //
    // Compared against "real" hashing (from the sticky-session code) and
    // "real" IP number conversion, this function is on par in terms of
    // worker index distribution only much faster.
    var worker_index = function(ip, len) {
        var s = '';
        for (var i = 0, _len = ip.length; i < _len; i++) {
            if (!isNaN(ip[i])) {
                s += ip[i];
            }
        }

        return Number(s) % len;
    };

    // Create the outside facing server listening on our port.
    var server = net.createServer({ pauseOnConnect: true }, function(connection) {
        // We received a connection and need to pass it to the appropriate
        // worker. Get the worker for this connection's source IP and pass
        // it the connection.
        var worker = workers[worker_index(connection.remoteAddress, num_processes)];
        worker.send('sticky-session:connection', connection);
    }).listen(port);
} else {
    // Note we don't use a port here because the master listens on it for us.
    var app = new express();

    // Here you might use middleware, attach routes, etc.
    app.use('/assets', express.static(__dirname +'/public'));
    app.get('/', function(req, res){
        res.sendFile(__dirname + '/index.html');
    });


    // Don't expose our internal server to the outside.
    var server = app.listen(),
        io = socketio(server);

    // Tell Socket.IO to use the redis adapter. By default, the redis
    // server is assumed to be on localhost:6379. You don't have to
    // specify them explicitly unless you want to change them.
    io.adapter(socket_redis({ host: 'localhost', port: 6379 }));

    // Here you might use Socket.IO middleware for authorization etc.

    io.on('connection', function(socket) {
        console.log('New client connection detected on process ' + process.pid);

        socket.emit('welcome', {message: 'Welcome to BlueFrog Chat Room'});
        socket.on('new.message', function(message) {
            socket.emit('new.message', message);
        })

    });


    // Listen to messages sent from the master. Ignore everything else.
    process.on('message', function(message, connection) {
        if (message !== 'sticky-session:connection') {
            return;
        }

        // Emulate a connection event on the server by emitting the
        // event with the connection the master sent us.
        server.emit('connection', connection);

        connection.resume();
    });
}

2
  • What is not working? what have you tried? what's the problem? Commented Nov 30, 2016 at 10:13
  • the messages I send from a browser reaches my server and the message itself goes back to the same browser, but it does not get published to other browser... i think this has something to do with emitting i don't know. Commented Nov 30, 2016 at 10:20

2 Answers 2

1

If I understand correctly, your problem is that the messages from a client are not broadcasted to the other clients. you can solve this easily using :

io.on('connection', function(socket) {
    console.log('New client connection detected on process ' + process.pid);

    socket.emit('welcome', {message: 'Welcome to BlueFrog Chat Room'});
    socket.on('new.message', function(message) {
        socket.emit('new.message', message);  // this line sends the message back to the emitter
        socket.broadcast.emit('my message', msg); // this broadcasts the message to all the clients
    })

});
Sign up to request clarification or add additional context in comments.

Comments

1

There are different ways to emit a message. The one you're using emits the message only to the socket that first sent a 'new.message' message to the server. Which means that a socket will receive the message that you emit there only if it first sent a message 'new.message'. That's why, in your browser, the client originating the message is the only one receiving it back.

Change it to:

    socket.on('new.message', function(message) {
        io.sockets.emit('new.message', message);//use this if even the browser originating the message should be updated.
        socket.broadcast.emit('new.message', message);//use this if everyone  should be updated excpet the browser source of the message.
    })

Here are the different ways you can emit:

io.sockets.on('connection', function(socket) {
    //This message is only sent to the client corresponding to this socket.
    socket.emit('private message', 'only you can see this');

    //This message is sent to every single socket connected in this 
    //session, including this very socket.
    io.sockets.emit('public message', 'everyone sees this');

    //This message is sent to every single connected socket, except
    //this very one (the one requesting the message to be broadcasted).
    socket.broadcast.emit('exclude sender', 'one client wanted all of you to see this');
});

You can also add sockets to different rooms when they connect so that you only communicate messages with sockets from a given room:

io.sockets.on('connection', function(socket) {
    //Add this socket to a room called 'room 1'.
    socket.join('room 1');

    //This message is received by every socket that has joined 
    //'room 1', including this one. (Note that a socket doesn't
    //necessarily need to belong to a certain room to be able to
    //request messages to be sent to that room).
    io.to('room 1').emit('room message', 'everyone in room 1 sees this');

    //This message is received by every socket that has joined 
    //'room 1', except this one.
    socket.broadcast.to('room 1').emit('room message', 'everyone in room 1 sees this');
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.