NodeJS 聊天工具 如何实现点对点客户端间传递消息?

最近在学习node,其中一个很感兴趣的项目是制作聊天工具。

起初是建立服务端与客户端的一个socket连接,然后互相发消息,
现在想做两个客户端之间通讯,问题来了..

clients变量是一个数组,里面存储了socket对象,一旦有新的连接那么就会把新的socket对象push进去,

clipboard.png

如果做群发消息的话,只要给clients遍历然后发消息,那么每个客户端都能收到消息,

clipboard.png

现在的问题是我想做客户端与客户端之间的通讯,那么就要从这个数组中取出这个特定的客户端, 请问怎么能拿出那个特定的客户端?
问题转化成了怎么成数组中拿出这个特定的对象..
下图这样写会报错

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;
          // 我们要发给客户端的东西
          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;

        // 我们要发给客户端的东西
        var send = {
            protocal:signal.protocal,
            from:username,
            message:message
          };

        console.log(`${username}要发给${target}的内容是${message}`); 


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

  }

   

    function clientData( chunk)  {

        // chunk:broadcast|张三|弄啥咧!
        //        协议     用户名 消息
        // 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('协议的protocal字段有问题!');
                    break;
            }

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

        }
        catch (err) {
            socket.write('数据格式有问题!');
            throw err;
        }

        // 有任何客户端发消息都会触发
        // 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(`服务器正常启动监听【${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('姓名有问题!');
    //创建与服务端的连接

    //还可以传入一个参数host:192.xx...
    var socket = net.createConnection({ port: 2080 }, () => {



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


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

        //监听服务端发过来的数据
        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('数据协议字段有问题');
                        break;
                }
            }
            catch (err) {
                socket.write('数据格式有问题!');
                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

阅读 2.8k
1 个回答

代码好多,我是否理解最后的问题就是

问题转化成了怎么成数组中拿出这个特定的对象..

只要push之前做好标示,这个socket是哪个人的,比如clients.push({username:'one', socket:socket }),然后需要的时候从clients.find({username:'one'))就可以了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题