1

I'm currently developing an instant messaging application but I have an issue saving the users that log into the server. I know that I have to store the socket resource of the connection event of each user that connects, however I can't have all those resources available when I access the server on different browsers.

The problem

here's part of the server:

//..

//..

var users = {};
    io.sockets.on('connection', function (socket) {         
    users[req.session.name] = socket;

    socket.on('msgToServer', function (data) {
        users[data['to']].emit('msgFromServer',{message:data['message'],to:data['from'],from:data['to']});              
    });
}); 

when I send a message from one browser who uses one session to another who uses an another one.. the code breaks:

C:\Archivos de programa\nodejs\session\data_handler.js:142   
users[data['to']].emit('msgFromServer',{message:data['message'],to:data['from                                                                                                           
                   ^
TypeError: Cannot call method 'emit' of undefined at Socket.<anonymous> (C:\Archivos de programa\nodejs\session\data_handler.js:142:20)

because If I log in with one account(like charlie), the server holds

var users = {};
    io.sockets.on('connection', function (socket) {         
    users['charlie'] = socket; <-- charlie's socket resource

users['charlie'] is available if I send a message from the browser that charlie logged in ... only, so like if charlie only can send messages to himself because there are no more socket resources in the user object, so when I try to send a message to the pedros's account, for instance... that resource is not available(undefined) and the server throws that error. What I need is a means of having all users that log in from one user agent... in a container,not necessarily an object, in this case : users. So data['to'] would not be undefined and msgFromServer events could be sent arbitrarily to users:

server

var express = require('express');
app = express(),
    server = require('http').createServer(app),
    io = require('socket.io').listen(server);

app.use(express.static( __dirname));
app.use(express.bodyParser());
app.use(express.cookieParser());

var MemcachedStore = require('connect-memcached')(express);

app.use(express.session({ 
    secret: 'lolz',
    store:new MemcachedStore 
})); 

var connection = function(){
    var mysql = require('mysql');

    var mysql = mysql.createConnection({
        host: 'localhost',
        port: 3306,
        user: 'root',
        password: '',
    });

    mysql.query('use test');

    return mysql;
};


app.post('/data', function(req, res){

    var username = req.body.username;
    var password = req.body.password;

    var mysql = connection();

    mysql.query("select username from user where username like '"+ username +"' and password like '"+password +"'",
    function(err, result, fields) {
        if (err) throw err;
        else {

            if(result != ''){
                req.session.name  = username;

                mysql.query("update user set online = 1 where id like  '"+req.session.name+"' ");

                res.redirect("/welcome_user");
            }
            else{
                res.end("You are not registered");
            }
        }
        }); 

});

app.get("/welcome_user",function(req,res){
    var html = '<html>\n'+
        '<head>\n'+
        '<link rel="stylesheet" type="text/css" href="styles/jquery-ui-1.8.18.custom.css">\n'+
        '<link rel="stylesheet" type="text/css" href="styles/styles.css">\n'+
        '<style>    \n  #onlineUsers{border: 1px solid black; width: 300px;}</style>\n'+
        '<script src="http://127.0.0.1/socket.io/lib/socket.io.js"></script>\n'+
        '<script src="scripts/jquery.js"></script>\n'+
        '<script type="text/javascript" src="scripts/jquery-ui-1.8.18.custom.min.js"></script>\n'+
        '<script src="scripts/chatbox.js"></script>\n'+
        '<script src="scripts/send.js"></script>\n'+
        '<script>\n'+
        "//receive();\n"+
        '$(function(){\n'+
            '$("#onlineUsers li").dblclick( function(event){\n  '+"createChatbox($.trim($(this).text()), '"+req.session.name+"','');\n"+
            '} );'+
        '});'+
    '</script>\n'+
'</head>\n'+
'<body>\n'+
        '<h1>Hola  '+req.session.name+'. Estos son los  usuarios en linea </h1> \n'+'<div id="onlineUsers"><ol>\n';
    mysql = connection();

    mysql.query("select username from user where online = 1 and username != '"+req.session.name+"' ", 
        function(err, results, fields) {
            if (err) throw err;

            for (var index in results) {
                html += '<li>' + results[index].username + '</li>';             
            }
            html +='</ol></div> \n'+
            '</body>\n'+
            '</html>';
            res.writeHead(200, {'Content-Type': 'text/html'});
            res.end(html);
        }
    );
    var users = {};
    io.sockets.on('connection', function (socket) {
        users[req.session.name] = socket;

        socket.on('msgToServer', function (data) {
            for (var u in users){
                console.log("%s | %s",u,users[u]);

                 /*
                   this is how  I determine that the user that logged in 
                   is not available in the user object

                  */
        }



        users[data['to']].emit('msgFromServer' {message:data['message'],to:data['from'],from:data['to']});
        });
    });      
});


server.listen(80);

client:

function createChatbox(to,from,message){    
    $('<div id ="chatbox" class='+to+'>  <div id="messageOutput" > <textarea class="readOnly" readonly="readonly" rows="4" cols="30"></textarea></div><br /> <hr /> <div id="messageInput"> <textarea class ="editable" rows="2" cols="30"> </textarea> </div> </div>').appendTo("body").dialog({draggable:true, title:to}) ;        

    if(message !='')
        $('#chatbox.'+to+' #messageOutput textarea.readOnly').text(message);

    $("textarea.editable").keydown(function(event){
        if(event.which == 13 && $(this).val() != ''){
            send(to,from,$.trim($(this).val()));
            $(this).val('');
            return false;
        }
    });
}

var socket = io.connect('http://localhost');

function send(to, from, message){
    socket.emit('msgToServer',{message:message,to:to,from:from});   
} 

socket.on('msgFromServer', function (data) {
    message = data['message'],
    from = data['from'],
    to = data['to'];            

    if($('#chatbox.'+from).dialog("isOpen") === true){
        $('#chatbox.'+from+' #messageOutput textarea.readOnly').text(message);      
    }

    else if(($('#chatbox.'+from).dialog("isOpen") !== true)){
        createChatbox(from,to,message);
    }
});
Charlie
  • 183
  • 2
  • 14
  • check out [rooms](https://github.com/LearnBoost/socket.io/wiki/Rooms) and also this [awesome post](http://stackoverflow.com/questions/10058226/send-response-to-all-clients-except-sender-socket-io/10099325#10099325). It shouldn't be to hard to send a message to a specific socket with some JSON object, as long as your keeping all of the important information on the server. – Loourr Jan 05 '13 at 21:32
  • Yeah I have seen those links. You mentioned something very important, though: "as long as your keeping all of the important information on the server" , that's exactly what I can't achieve; I can't keep the resources to emit the messages in the server. – Charlie Jan 06 '13 at 22:35
  • You gotta define `var users = {}; io.sockets.on('connection',...` outside of `app.get("/welcome_user",function(req,res){` and that will fix it. It's because you are redefining the users object everytime something is requested. – Farid Nouri Neshat Dec 18 '16 at 18:42

0 Answers0