如何将多个socketId与socket.io和express.js对象中的一个昵称相关联?

时间:2013-12-31 23:17:11

标签: node.js session express socket.io

我正在使用此节点聊天窗口小部件:https://github.com/wwwizzarrdry/mini_chat/

  1. 您可以在相同的昵称下打开多个标签/窗口,聊天工作正常(即所有消息似乎来自相应的用户,无论他们从哪个窗口发送)。
  2. 问题在于我的耳语功能。向用户发送私人消息时,我只能将其发送到该用户的最后一个socketId。因此,如果打开4个窗口,则仅在最后一个窗口中收到耳语。
  3. 问:我如何允许在同一个昵称下打开多个套接字,但是在该用户的所有窗口中保持耳语功能? 我能够为所有连接的用户建立一个sessionId,但是一旦建立了套接字,就不知道如何将套接字重新分配给用户。

    App.js Key Blocks:

        var express = require('express'),
        app = express(),
        server = require('http').createServer(app),
        io = require('socket.io').listen(server),
        mongoose = require('mongoose'),
        users = {};
    
        server.listen(3000);
    
        ........
    
        io.sockets.on('connection', function(socket){
        var query = Chat.find({});
        query.sort('-created').limit(25).exec(function(err, docs){
                if(err) throw err;
                socket.emit('load old msgs', docs);
        });
    
        socket.on('new user', function(data, callback){
                if (data in users){
                        callback(false);
                } else{
                        callback(true);
                        socket.nickname = data;
                        users[socket.nickname] = socket;
                        updateNicknames();
                }
        });
    
        function updateNicknames(){
                io.sockets.emit('usernames', Object.keys(users));
        }
    
        .......
    
        socket.on('send message', function(data, callback){
        var msg = data.trim();
        console.log('after trimming message is: ' + msg);
        if(msg.substr(0,3) === '/w '){
            msg = msg.substr(3);
            var ind = msg.indexOf(' ');
            if(ind !== -1){
                var name = msg.substring(0, ind);
                var msg = msg.substring(ind + 1);
                if(name in users){
                    users[name].emit('whisper', {msg: msg, nick: socket.nickname});
                    console.log('message sent is: ' + msg);
                    console.log('Whisper!');
                } else{
                    callback('Error!  Enter a valid user.');
                }
            } else{
                callback('Error!  Please enter a message for your whisper.');
            }
        } else{
            var newMsg = new Chat({msg: msg, nick: socket.nickname});
            newMsg.save(function(err){
                if(err) throw err;
                 io.sockets.emit('new message', {msg: msg, nick: socket.nickname});
            });
        }
    
        .......
    

    更新:使用'rooms'工作得很漂亮。

        socket.on('new user', function(data, callback){
                if (data in users){
                        callback(true);
                        socket.nickname = data;
                        users[socket.nickname] = socket;
                        **socket.join(socket.nickname);**
                        updateNicknames();
                } else{
                        callback(true);
                        socket.nickname = data;
                        users[socket.nickname] = socket;
                        **rooms.push(socket.nickname);
                        socket.join(socket.nickname);**
                        updateNicknames();
                }
        });
    
        .......
    
        socket.on('send message', function(data, callback){
                var msg = data.trim();
                console.log('after trimming message is: ' + msg);
                if(msg.substr(0,3) === '/w '){
                        msg = msg.substr(3);
                        var ind = msg.indexOf(' ');
                        if(ind !== -1){
                                var name = msg.substring(0, ind);
                                var msg = msg.substring(ind + 1);
                                if(name in users){
                                          **io.sockets.in(name).emit('whisper', {msg: msg, nick: socket.nickname});**
                                          *//users[name].emit('whisper', {msg: msg, nick: socket.nickname});*
                                          console.log('message sent is: ' + msg);
                                          console.log('Whisper!');
                                } else{
                                        callback('Error!  Enter a valid user.');
                                }
                        } else{
                                callback('Error!  Please enter a message for your whisper.');
                        }
                } else{
                        var newMsg = new Chat({msg: msg, nick: socket.nickname});
                        newMsg.save(function(err){
                                if(err) throw err;
                                io.sockets.emit('new message', {msg: msg, nick: socket.nickname});
                        });
                }
        });
    

1 个答案:

答案 0 :(得分:1)

我认为有两种方法可以做到这一点:

  • 为在同一昵称下运行的每组窗口/标签创建一个房间。来自socket.io's docs
  

会议室允许对连接的客户端进行简单分区。这允许   要发送到连接的客户端列表的子集的事件,和   提供了一种管理它们的简单方法。

基本上,对于每个昵称,创建一个房间(可能是昵称的唯一哈希),每当您需要耳语时,只需将其发送到该房间即可。

  • 跟踪特定于每个客户端的所有窗口/选项卡的套接字ID,并将其保存在数据库中。然后,一旦您需要播放耳语,只需查询所有ID,并向他们发送whisper消息。这种方法的缺点是你需要对数据库进行一些内务管理(主要是删除断开的套接字ID)。

就个人而言,我会选择第一种方法,因为它可以带来良好的学习体验。