我们实现的思路是,当有一个人发送过来消息,我们就广播给其他客户端。
var net = require('net'); var chatServer = net.createServer(), clientList = [];//已连接的client列表 chatServer.on('connection', function(client) { // name 的自定义属性,用于表示哪个客户端(客户端的地址+端口为依据) client.name = client.remoteAddress + ':' + client.remotePort; client.write('Hi ' + client.name + '!\n'); //加入在线列表 clientList.push(client); client.on('data', function(data) { broadcast(buffer, client);// 发送给其他客户端 }); client.on('end', function() { //从在线列表中移除 clientList.splice(clientList.indexOf(client), 1); }); });
chatServer.listen(9000);
这里broadcast方法发送给其他客户端,代码如下
function broadcast(message, client) { for(var i=0;i<clientList.length;i+=1) { //发送给其他人 if(client !== clientList[i]) { var msg=client.name + " says: " + message; console.log(msg); clientList[i].write(msg); } } }
但此时,我们会发现,每发送一个字符,其他客户端都会收到一条消息。
比如我们发送”abcd“,如果client.name为”192.168.1.2:5486“,其他用户收到的是:
192.168.1.2:5486 says: a
192.168.1.2:5486 says: b
192.168.1.2:5486 says: c
192.168.1.2:5486 says: d
此时,我们需要考虑分割符将我们要发送的完整的一句话分开,最终我采取的是回车换行分割。最终代码如下:
// 在前者的基础上,实现 Client --> Sever 的通讯,如此一来便是双向通讯 var net = require('net'); var chatServer = net.createServer(), clientList = [];//已连接的client列表 var clientsBuffer={}; //telnet 127.0.0.1 9000 chatServer.on('connection', function(client) { // name 的自定义属性,用于表示哪个客户端(客户端的地址+端口为依据) client.name = client.remoteAddress + ':' + client.remotePort; client.write('Hi ' + client.name + '!\n'); clientList.push(client); clientsBuffer[client.name]=new Buffer(0);//发送消息的缓存 client.on('data', function(data) { console.log(data); var myBuffer=clientsBuffer[client.name]; console.log(myBuffer); //以回车换行为分割 if(data.equals(new Buffer([0x0d,0x0a]))){ broadcast(myBuffer, client);// 接受来自客户端的信息 clientsBuffer[client.name]=new Buffer(0);//清空缓存 }else{ //将发送过来的字符拼入缓存中 var buflist=[myBuffer,data]; clientsBuffer[client.name]=Buffer.concat(buflist,myBuffer.length+data.length); } }); client.on('end', function() { clientList.splice(clientList.indexOf(client), 1); // 删除数组中的制定元素。这是 JS 基本功哦~ }); client.on('error', function(e) { console.log(e); }); }); /** * 广播给其他所有用户 * @param message 消息内容 * @param client 发送人客户端 */ function broadcast(message, client) { var cleanup = [];//需要销毁的列表 for(var i=0;i<clientList.length;i+=1) { if(client !== clientList[i]) { if(clientList[i].writable) { // 先检查 sockets 是否可写 var msg=client.name + " says " + message; console.log(msg); clientList[i].write(msg); } else { cleanup.push(clientList[i]) // 如果不可写,收集起来销毁。销毁之前要 Socket.destroy() 用 API 的方法销毁。 clientList[i].destroy() } } } //销毁 for(i=0;i<cleanup.length;i+=1) { clientList.splice(clientList.indexOf(cleanup[i]), 1) } } chatServer.listen(9000);