首页 > nodejs中的TCP聊天程序求助?

nodejs中的TCP聊天程序求助?

下面这段代码的for语句中,当我开启两个客户端时,一个客户端发送的消息用users[i].write输出对方就可一收到消息,为什么用conn.write输出对方就收不到消息,而且明明是个for循环,消息不应该是连续输出两次吗?

var net=require('net');

var count=0,users={};
var server=net.createServer(function(conn){
    conn.setEncoding('utf-8');
    var nickname;
    conn.write(
        '\n > welcome to node-chat!'
        +'\n > '+ count + ' other people are connected at this time.'
        +'\n > please write your name and press enter:'
    );
    count++;
    conn.on('data',function(data){
        data=data.replace('\r\n','');
        if(!nickname){
            if(users[data]){
                conn.write('>nickname already in use,try again:');
                return;
            }else{
                nickname=data;
                users[nickname]=conn;
                for(var i in users){
                    **users[i].write('>'+ nickname + ' joined the room\n');**
                }
            }
        }    
    });
    conn.on('close',function(){
        count--;
    });
});

server.listen(3000,function(){
    console.log('server listening on *:3000');
});

在user对象中以用户的nickname为key,保持了其持有的连接
有N个用户,就会有N个userKey,同时对应N个tcp连接
消息广播必须通过用户对应的conn发送,客户端才能收到

for(var userKey in users){
    conn.write('>'+ nickName + ' joined the room\n');
}

这个conn是当前触发data事件的那个用户的TCP连接,conn.write就是给自己发送消息~~~~

for(var userKey in users){
   users[userKey].write('>'+ nickName + ' joined the room\n');
}

遍历用户,并且取出对应的TCP连接,发送消息~~

另外:
代码可以优化下,nickName这个变量没有用的~~~

var nickName=data.replace('\r\n','');
if(users[nickName]){
    conn.write('>nickname already in use,try again:');
    return;
}else{
    users[nickName]=conn;
    for(var userKey in users){
        users[userKey].write('>'+ nickName + ' joined the room\n');
    }
}

欢迎参考NoNOIM,支持TCP,Redis作为信息缓存。


看你的代码是想广播消息吧?
users声明在回调函数里可能会有问题哦,每次回调函数执行都有独立的作用域,上次保存的user就没有了


这是一个闭包的问题!
如果你懂闭包,这个很简单,如果不懂,就解释起来有点麻烦了。

假设,你 server=net.createServer那句中的那个匿名函数叫做newConn(匿名函数没办法说),conn.on('data') 那个函数叫做newMsg,上述代码可以部分等价为

function newConn(conn)
{
    // 其他代码
    function newMsg(data)
    {
        // 这里使用了变量 conn
    }
    conn.on('data',newMsg);
}
server=net.createServer(newConn);

每一次新用户链接就是执行一次 newConn 而在newConn 中有个局部变量conn,同时也创建了一个新的函数newMsg
每次来一个链接,都会执行newConn,也就是会创建多个局部变量connnewMsg,他们之间有着对应关系。在newMsg函数监听了对应的conndata事件。

所以当某个客户端发送消息之后,会用某个 newMsg 来处理,而其中的newConn就是对应的conn就是当前发送消息的这个变量。因此只有发送消息的这个用户可以收到(如果循环的话会收到多次)。
而user就不同了,user是全局变量,保存了所有的conn,所以遍历一次就会发送给每一个conn一个消息。


你的代码中没有体现,你用 conn.write 时的用法.
请提供你运行不正常的代码.

【热门文章】
【热门文章】