NodeJs開發的CLI——與telnet進行通信的聊天程序


前言: (在NodeJs中,我們想要開啟一個tcp協議的做法就是引入net內置對象: 

        const net = require('net'); ——ES6

        var net = require('net'); ——ES5)

今天,我們來實現一個

  基於TCP協議完成node服務器與telnet客戶端通信的聊天程序

首先,思考我們的需求

     1.開啟多個終端頁面,可在不同終端中進行用戶注冊,注冊成功后,即開始聊天

     2.使用net開啟TCP服務,net.stream的設計

具體實現界面貼圖:

我們需要做的有兩件事

     1.用NodeJs搭建服務器流 ——to dev

     2.實現telnet可視化界面 ——to user

那么,我們就開始用NodeJs搭建服務器

    • 首先思考,我們是通過TCP協議進行通信,那么選用net模塊(nodejs內置)
    • 其次,我們使用net.createServer創建一個服務,createServer方法中參數為一個回調函數,符合事件驅動概念,該回調函數中的參數為connection對象,咱們就使用該對象進行net.stream數據流的傳遞

濾清思路后,我們開始:

const net = require('net'); // 介於目前ES2015已成新標准,所以采用ES6寫法
 let server = net.createServer(function (conn) { // ...code
};

在上述代碼中,我們創建了一個server服務器,接下來我們思考,我們的服務器需要對端口進行監聽:

const net = require('net'); // 介於目前ES2015已成新標准,所以采用ES6寫法
 let server = net.createServer(function (conn) { // ...code
}; server.listen(3000, function () { console.log('\033[96m    server listening on *:3000\033[39m'); });

監聽端口號為3000,當我們啟動服務器時,可以在終端中顯示: 

接下來我們嘗試用telnet客戶端連接咱們剛搭建好的服務器:(在命令行或者終端內輸入 telnet 127.0.0.1 3000)

*Telnet協議TCP/IP協議族中的一員,是Internet遠程登陸服務的標准協議和主要方式

*若您不知道如何打開telnet,請閱讀——<如何在windows10下開啟telnet服務>

那么,我們在telnet客戶端界面看到,目前沒有任何顯示,所以我們需要去設計一個用戶使用的界面:

效果如圖:

我們考慮:如何在終端上顯示提示符?

connection對象上提供了write方法,可以在通過連接的客戶端上顯示輸入內容,所以我們在server對象內部設計用戶界面:

let server = net.createServer(function (conn) { // 頁面tip
 conn.write( '\n > welcome to \033[92mnode-chat\033[39m!'
        + '\n > ' + count + ' other people are connected at this time.'
        + '\n > please write your name and press enter: ' ); };

此時,重新利用終端開啟telnet,此時用戶界面顯示如上圖。

既然已經設計好用戶注冊界面,那么我們應該去考慮如何處理用戶輸入的數據,這時,我們需要通過connection對象對輸入數據注冊事件:

let count = 0;
// 參數count作計算接入客戶端數

let server = net.createServer(function (conn) {
count++;
// 頁面tip conn.write( '\n > welcome to \033[92mnode-chat\033[39m!' + '\n > ' + count + ' other people are connected at this time.' + '\n > please write your name and press enter: ' ); conn.on('data', function (data) { // ... code } };

data參數就是用戶輸入的數據了,不過我們考慮,用戶首先輸入的應該是用戶名其次才是聊天數據,所以我們應該:

    1.用列表對用戶名進行保存

    2.判斷用戶名是否第一次輸入信息,以便重新注冊

    3.判斷用戶輸入昵稱是否已存在

let count = 0; let users = {}; let server = net.createServer(function (conn) { count++; let nickname; // 頁面tip
 conn.write( '\n > welcome to \033[92mnode-chat\033[39m!'
        + '\n > ' + count + ' other people are connected at this time.'
        + '\n > please write your name and press enter: ' ); conn.on('data', function (data) { // 刪除回車符,否則會出現空行
        data = data.replace('\r\n', ''); if (!nickname) { if (users[data]) { conn.write('\033[93m> nickname already in use. try again:\033[39m '); return; } else { nickname = data; users[nickname] = conn; // 將conn對象賦予用戶,賦予用戶可操作權限
 } } else { // 驗證用戶為已注冊,則輸入數據data為聊天信息
             for (var i in users) { if (i != nickname) { console.log('\033[96m > ' + nickname + ':\033[39m ' + data + '\n'); } } } } };

實現后效果:

用戶關閉客戶端時,我們不想保存用戶名,我們可以注冊close事件:

let count = 0; let users = {}; let server = net.createServer(function (conn) { count++; let nickname; // ...code
    // 當其中某個用戶斷開連接時,需要清楚數據
    conn.on('close', function () { count--; console.log('\033[90m > ' + nickname + ' left the room\033[39m\n'); delete users[nickname]; }); };

 

到目前為止,我們已經實現了整個聊天程序的功能,那么我們應該思考代碼重構:

我們在用戶接入與斷開連接時,都寫入了提示信息,那么,我們應該將提示信息抽離出來,作為一個廣播函數:

let count = 0; let users = {}; let server = net.createServer(function (conn) { count++; let nickname; // ...code
    // 當用戶退出時,進行廣播通知
    let broadcast = (msg, exceptMyself) => { for (var i in users) { if (!exceptMyself || i != nickname) { users[i].write(msg); } } }; // 監聽用戶行為作出處理
    conn.on('data', function (data) { // 刪除回車符
        data = data.replace('\r\n', ''); if (!nickname) { if (users[data]) { conn.write('\033[93m> nickname already in use. try again:\033[39m '); return; } else { nickname = data; // 將conn對象賦予用戶,賦予用戶可操作權限
                users[nickname] = conn; broadcast('\033[90m > ' + nickname + ' joined the room\033[39m\n'); } } else { // 驗證用戶為已注冊,則輸入數據(data)為聊天信息
            for (var i in users) { if (i != nickname) { broadcast('\033[96m > ' + nickname + ':\033[39m ' + data + '\n', true); } } } }); // 當其中某個用戶斷開連接時,需要清楚數據
    conn.on('close', function () { count--; broadcast('\033[90m > ' + nickname + ' left the room\033[39m\n'); delete users[nickname]; }); };

實現廣播效果:

加入:

 

退出(關閉客戶端):

*注:處理data數據時應設置編碼格式  conn.setEncoding('utf8');

至此,我們的整個聊天程序就大功告成了!

大家可以在我的github上獲取源碼——https://github.com/TimRChen/NodeCLI-telnet

相應操作文檔——click here!

 


免責聲明!

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



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