初始实现
var net = require(‘net‘);//1 引入net模块 ?var chatServer = net.createServer();//创建net服务器 ?var clientList=[];//保存多个客户端的数组 ?chatServer.on(‘connection‘, function (client) {//服务器连接客户端 ?????client.name=client.remoteAddress+‘:‘+client.remotePort; ?????/*增加name属性*/ ?????client.write(‘Hi‘+client.name+‘!\n‘); ?????clientList.push(client); ?????client.on(‘data‘, function (data) { ?????/*添加事件监听器,这样就可以访问到连接事件所对应的client对象,当client发送数据给服务器时,这一事件就会触发*/ ?????????for(var i=0;i<clientList.length;i++){ ?????????????if(clientList[i]!==this){ ?????????????????// 把数据发送给其他客户端 ?????????????????clientList[i].write(this.name+"says "+data); ?????????????} ?????????} ?????}); ?}); ?chatServer.listen(9000, "127.0.0.1");//服务器端口
注意:这里有个坑——如果有个客户端断开连接,那么所有人都会玩完!
因为如果再往服务器发送消息,这时候服务器并不知道某个客户端已经断开了连接,因此会继续向其发送数据,但是这时断开的这个客户端对应的socket已经无法写入数据,而对已关闭的socket进行write()操作node程序会抛出异常,进而导致全军覆没。所以,这个问题应该从两个方面来解决:
(1)当客户端断开连接时,通知服务器,将其从客户端列表中移除,防止其调用write方法(V8引擎也会把响应的socket对象作为垃圾回收,并释放相应的内存);
(2)采用更保险的方式调用write()方法。
改进如下:
最后,监听客户端关闭事件,并记录错误
var net = require(‘net‘);//1 引入net模块 ?var chatServer = net.createServer();//创建net服务器 ?var clientList = [];//保存多个客户端的数组 ?chatServer.on(‘connection‘, function (client) {//服务器连接客户端 ?????// console.log(‘ client remoteAddress =‘ + client.remoteAddress); ???// console.log(‘ client remotePort = ‘ + client.remotePort); ???client.name = client.remoteAddress + ‘:‘ + client.remotePort; ?????/*增加name属性*/ ?????client.write(‘Hi‘ + client.name + ‘!\n‘); ?????// console.log(‘‘client.name+‘connected‘); ???clientList.push(client); ?????console.log(‘clientList length = ‘ + clientList.length); ???for(var i = 0; i<clientList.length; i++){ ?????console.log(‘client remoteAddress‘+[i] + clientList[i].name); ???} ???client.on(‘data‘, function (data) { ?????????/*添加事件监听器,这样就可以访问到连接事件所对应的client对象,当client发送数据给服务器时,这一事件就会触发*/ ????????//广播消息给其他客户端 ?????????broadcast(data,client); ?????}); ???//监听客户端终止 ?????client.on(‘end‘,function(){ ?????????console.log(‘‘+client.name+‘quit‘);//如果某个客户端断开连接,node控制台就会打印出来 ?????????clientList.splice(clientList.indexOf(client),1); ?????}); ?????/*记录错误*/ ?????client.on(‘error‘,function(e){ ?????????console.log(‘ error‘+e); ?????});function broadcast(message,client){ ?????????var cleanup=[];//断开了的客户端们 ?????????for (var i = 0; i < clientList.length; i++) { ?????????????if (clientList[i] !== client) { ?????????????????//检查socket的可写状态 ?????????????????if (clientList[i].writable) { ?????????????????????// 把数据发送给其他客户端 ?????????????????????clientList[i].write(client.name + "says " + message); ?????????????????}else{ ?????????????????????/*socket不可写,则将其从列表中移除*/ ?????????????????????cleanup.push(clientList[i]); ?????????????????????clientList[i].destroy(); ?????????????????} ?????????????} ?????????} ?????????/*删除掉服务器的客户端数组中,已断开的客户端*/ ?????????for(var i=0;i<cleanup.length;i++){ ?????????????clientList.splice(clientList.indexOf(cleanup[i]),1); ?????????} ?????} ?}); ?//服务器端口 ?chatServer.listen(9000, function(){ ???console.log("server bound : 9000");});
nodejs 服务器实现区分多客户端请求服务
原文地址:https://www.cnblogs.com/cangqinglang/p/9865398.html