zoukankan      html  css  js  c++  java
  • nodejs初探(四)实现一个多人聊天室

    样例地址http://www.lxrtalk.com/

    我们实现的思路是,当有一个人发送过来消息,我们就广播给其他客户端。

    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 + '!
    ');
      //加入在线列表
        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 + '!
    ');
        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);
  • 相关阅读:
    JAVA 从一个List里删除包含另一个List的数据
    CentOS 常用命令合集
    010---软链接和硬链接
    009---linux进程管理
    008---vim编辑器
    007---归档、压缩、解压缩
    006---Linux用户、群组和权限
    005---Linux文件与目录管理
    001---Linux系统的启动过程
    002---Linux系统目录结构
  • 原文地址:https://www.cnblogs.com/lixiaoran/p/5041015.html
Copyright © 2011-2022 走看看