【管子先生的Node之旅·17】开发一款TCP的聊天程序

需求

  • 创建一个可以多人即时通讯的聊天室。
  • 用户加入时必须要设置昵称,且昵称不能相同。
  • 用户加入成功打印出成功欢迎信息和当前在线人数,并通知聊天室内其他的人。
  • 用户发送信息时,需要广播到所有的用户。
  • 当某一用户离开时也需要通知到所有的用户。

效果演示

net.gif

程序实现

服务端
//tcpServer.js
// 引入colors模块
require('colors');
// 引入net模块
const net = require('net');
// 在线计数器
var count = 0,
    users = {};
// 创建服务
const serv = net.createServer((conn) => {
    console.log('有用户进来了'.red);
    // 用户欢迎信息
    conn.write('\n你好!欢迎来到管子聊天室!'.rainbow);
    // conn.write('\nOnline=>'.green + count);
    conn.write('\n请输入你的昵称:'.red);
    // 设置编码
    conn.setEncoding('utf-8');
    count++;
    // 代表当前链接的昵称
    let nickName;
    // 接收处理用户数据
    conn.on('data', (data) => {
        // 第一次用户回复数据视为设置昵称
        if (!nickName) {
            // 判断昵称是否已被占用
            if (users[data]) {
                conn.write('\n该昵称已被占用,请重新设置:'.red);
                return;
            } else {
                nickName = data;
                users[nickName] = conn;
                console.log(Object.keys(users));
                // 发布用户加入广播
                broadcast('\n欢迎 ' + nickName);
                broadcast('\n当前在线=>'.green + count);
                conn.write('\n欢迎 ' + nickName);
                conn.write('\n当前在线=>'.green + count);
            }
        } else {
            // 聊天消息
            broadcast('\n' + nickName + data.split('\r')[0]);
        }
    });
    // 监听用户离线
    conn.on('close', (c) => {
        console.log('有用户离开了'.red);
        count--;
        broadcast('\n离线=>'.red + nickName);
        broadcast('\n当前在线=>'.green + count);
        //将用户从中删除
        delete users[nickName];
    });
    // 错误处理
    conn.on('error', (err) => {
        console.error(err);
    });
    // 用户广播

    function broadcast(val) {
        for (let i in users) {
            if (i !== nickName) {
                console.log(new String(i));
                console.log(new String(nickName));
                console.log(i == nickName);
                users[i].write(val + ++sm);
            }
        }
    }
});

serv.listen(3030, () => {
    console.log('服务已启动'.yellow);
});
客户端
//引入net模块
const net = require('net');
//端口
const port = 3030;
//地址
const host = '127.0.0.7';
//链接tcp服务端
const client = net.connect(port, host);
//设置编码
client.setEncoding('utf-8');
//监听是否链接成功
client.on('connect', () => {
    console.log('tcp服务器已连接');
});
//接收服务器数据
client.on('data', (data) => {
    process.stdin.pause()
    console.log(data);
    //打开输入流
    input();
});
//监听断开服务器
client.on('close', () => {
    console.log('用户断开了服务器');
});
//错误处理
client.on('error', () => {

});
//启动输入流
function input() {
    process.stdout.write('请输入');
    process.stdin.resume();
    process.stdin.setEncoding('utf-8');
    process.stdin.once('data', option);
}
//发送数据
function option(data) {
    //关闭用户输入
    process.stdin.pause()
    let datas = data.split('\r')[0];
    console.log(new String(datas));
    if (datas == 'exit') {
        //关闭与服务器的链接
        client.end('再见,各位!')
    } else {
        //往服务器发送数据
        client.write(datas);
    }
}

你可能感兴趣的:(【管子先生的Node之旅·17】开发一款TCP的聊天程序)