下面这段代码的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
,也就是会创建多个局部变量conn
和newMsg
,他们之间有着对应关系。在newMsg
函数监听了对应的conn
的data
事件。
所以当某个客户端发送消息之后,会用某个 newMsg
来处理,而其中的newConn
就是对应的conn
就是当前发送消息的这个变量。因此只有发送消息的这个用户可以收到(如果循环的话会收到多次)。
而user就不同了,user是全局变量,保存了所有的conn
,所以遍历一次就会发送给每一个conn
一个消息。
你的代码中没有体现,你用 conn.write
时的用法.
请提供你运行不正常的代码.