鍍金池/ 問答/Python  HTML/ NodeJS 聊天工具 如何實現(xiàn)點對點客戶端間傳遞消息?

NodeJS 聊天工具 如何實現(xiàn)點對點客戶端間傳遞消息?

最近在學習node,其中一個很感興趣的項目是制作聊天工具。

起初是建立服務端與客戶端的一個socket連接,然后互相發(fā)消息,
現(xiàn)在想做兩個客戶端之間通訊,問題來了..

clients變量是一個數(shù)組,里面存儲了socket對象,一旦有新的連接那么就會把新的socket對象push進去,

clipboard.png

如果做群發(fā)消息的話,只要給clients遍歷然后發(fā)消息,那么每個客戶端都能收到消息,

clipboard.png

現(xiàn)在的問題是我想做客戶端與客戶端之間的通訊,那么就要從這個數(shù)組中取出這個特定的客戶端, 請問怎么能拿出那個特定的客戶端?
問題轉(zhuǎn)化成了怎么成數(shù)組中拿出這個特定的對象..
下圖這樣寫會報錯

clipboard.png

clipboard.png

附上全部源代碼:

server.js:

// 建立一個Socket服務端
const net = require('net');

// 用于存儲所有的連接
var clients = [];

var server = net.createServer((socket) => {

    
    //socket對象push進去
    clients.push(socket);

    console.log(`${socket.remoteAddress}上線了,當前在線${clients.length}人`);
 

    socket.on('data',clientData).on('error',(err)=>{

        clients.splice(clients.indexOf(socket),1);
     
        console.log(`${socket.remoteAddress} 下線了 當前在線${clients.length}人`);
    
    });



    //廣播方法
    function broadcast(signal){
          console.log(signal);
          // 肯定有用戶名和消息
          var username = signal.from;
          var message = signal.message;
          // 我們要發(fā)給客戶端的東西
          var send = {
              protocal:signal.protocal,
              from:username,
              message:message
            };

          // 廣播消息
        clients.forEach(client => {
          client.write(JSON.stringify(send));        
        });

    }

    
    //點對點消息
    function p2p(signal){
        console.log(signal);
        // 肯定有用戶名和消息
        var username = signal.from;
        var target = signal.to;
        var message = signal.message;

        // 我們要發(fā)給客戶端的東西
        var send = {
            protocal:signal.protocal,
            from:username,
            message:message
          };

        console.log(`${username}要發(fā)給${target}的內(nèi)容是${message}`); 


        // 發(fā)送消息
        //clients[target].write(JSON.stringify(send));

  }

   

    function clientData( chunk)  {

        // chunk:broadcast|張三|弄啥咧!
        //        協(xié)議     用戶名 消息
        // chunk:{'protocal':'broadcast','from':'張三','message':''}
        // chunk:{'protocal':'p2p',from:'張三',to:'李四',message':''}


        try {
            var signal = JSON.parse(chunk.toString().trim());
            var protocal = signal.protocal;

            switch (protocal) {
                case 'broadcast':
                    broadcast(signal);
                    break;
                case 'p2p':
                    console.log('接收到了p2p消息!');
                    p2p(signal);
                    break;
                case 'shake':
                    shake(signal);
                    break;
                default:
                    socket.write('協(xié)議的protocal字段有問題!');
                    break;
            }

            // var username = signal.from;
            // var message = signal.message;

        }
        catch (err) {
            socket.write('數(shù)據(jù)格式有問題!');
            throw err;
        }

        // 有任何客戶端發(fā)消息都會觸發(fā)
        // var username = chunk.username;
        // var message = chunk.messge;
        // broadcast(username.message)
    };

});

var port = 2080;

server.listen(port, (err) => {
    if (err) {
        console.log('端口被占用了');
        return false;
    }
    console.log(`服務器正常啟動監(jiān)聽【${port}】端口`);
});

client.js:
//客戶端
const net = require('net');
const readline = require('readline');


const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

rl.question('What is your name? ', (name) => {

    name = name.trim();
    if (!name) throw new Error('姓名有問題!');
    //創(chuàng)建與服務端的連接

    //還可以傳入一個參數(shù)host:192.xx...
    var socket = net.createConnection({ port: 2080 }, () => {



        //登入操作;
        var user = {
            protocol: 'signin',
            username: name
        }


        console.log(`Welcome ${socket.remoteAddress} ${name} to 2080 chatroom`);

        //監(jiān)聽服務端發(fā)過來的數(shù)據(jù)
        socket.on('data', (chunk) => {
            try {
                var signal = JSON.parse(chunk.toString().trim());
                var protocal = signal.protocal;
                switch (protocal) {
                    case 'broadcast':
                        console.log(`[broadcast]"${signal.from}"說了:${signal.message}`);
                        rl.prompt();
                        break;
                    case 'p2p':
                        console.log(`[p2p]${signal.from}說了:${signal.message}`);
                        rl.prompt();
                        break;
                    default:
                        server.write('數(shù)據(jù)協(xié)議字段有問題');
                        break;
                }
            }
            catch (err) {
                socket.write('數(shù)據(jù)格式有問題!');
                throw err;
            }

        });





        rl.setPrompt(`${name}> `);

        rl.prompt();

        rl.on('line', (line) => {

            line = line.toString().trim();
            var temp = line.split(':');
            var send;

            if (temp.length === 2) {
                //點對點消息
                console.log('這是一個點對點消息');

                send = {
                    protocal: 'p2p',
                    from: name,
                    to: temp[0],
                    message: temp[1]
                };

            } else {
                //廣播消息

                // chunk:{'protocal':'broadcast','from':'張三','message':''}
                send = {
                    protocal: 'broadcast',
                    from: name,
                    message: line.toString().trim()
                };

            }

            socket.write(JSON.stringify(send));
            

            rl.prompt();

        }).on('close', () => {
            console.log('Have a great day!');
            process.exit(0);
        });

    });

});



使用:
--node server.js
--node client.js

回答
編輯回答
孤客

代碼好多,我是否理解最后的問題就是

問題轉(zhuǎn)化成了怎么成數(shù)組中拿出這個特定的對象..

只要push之前做好標示,這個socket是哪個人的,比如clients.push({username:'one', socket:socket }),然后需要的時候從clients.find({username:'one'))就可以了。

2017年1月26日 19:52