nodejs 服務器實現區分多客戶端請求服務


初始實現

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");
});

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM