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!
NodeJs开发的CLI——与telnet进行通信的聊天程序的更多相关文章
- CentOS 7快速搭建Nodejs开发环境
Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好.学习Nodejs首先需要会安装环境.这里我介绍如 ...
- 《Nodejs开发加密货币》之二十七:开发通用的HTML组件
人的懒惰常常是麻烦的开始.多数程序员都希望自己的工作一劳永逸,一次开发,到处使用,成了人人追逐的目标,我也不例外.最初写<Nodejs开发加密货币>系列文章,因为不喜欢设定好了去写,所以目 ...
- NodeJs 开发微信公众号(四)微信网页授权
微信的网页授权指的是在微信公众号中访问第三方网页时获取用户地理.个人等信息的权限.对于开发了自己的网页app应用时,获取个人的信息非常重要.上篇博客讲到了注册时可以获取用户的信息,很多人会问为什么还需 ...
- iOS开发之使用XMPPFramework实现即时通信(三)
你看今天是(三)对吧,前面肯定有(一)和(二),在发表完iOS开发之使用XMPPFramework实现即时通信(一)和iOS开发之使用XMPPFramework实现即时通信(二)后有好多的小伙伴加我Q ...
- iOS开发之使用XMPPFramework实现即时通信(二)
上篇的博客iOS开发之使用XMPPFramework实现即时通信(一)只是本篇的引子,本篇博客就给之前的微信加上即时通讯的功能,主要是对XMPPFramework的使用.本篇博客中用到了Spark做测 ...
- Win7搭建NodeJs开发环境以及HelloWorld展示—图解
Windows 7系统下搭建NodeJs开发环境(NodeJs+WebStrom)以及Hello World!展示,大体思路如下:第一步:安装NodeJs运行环境.第二步:安装WebStrom开发工具 ...
- ionic+nodejs开发遇到的跨域和post请求数据问题
最近学习ionic+nodejs开发混合app中遇到了一些问题,在此总结一下. 开发环境搭建 项目地址 https://github.com/ytudt/nodejsApp 代码和问题都会在之后的学习 ...
- nodejs开发指南读后感
nodejs开发指南读后感 阅读目录 使用nodejs创建http服务器; supervisor的使用及nodejs常见的调式代码命令了解; 了解Node核心模块; ejs模板引擎 Express 理 ...
- iOS开发多线程篇—线程间的通信
iOS开发多线程篇—线程间的通信 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任 ...
随机推荐
- swift 协议传值的实现
首先呢说下结构 一个ViewController 一个ModelViewController 在ModelViewController中定义了一个协议 这个逻辑 从第一个界面进入第二个界面 从第二个 ...
- I/O流
转自:http://www.cnblogs.com/dolphin0520/p/3791327.html 一.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的 ...
- OC基础了解篇
.h文件存放声明 .m文件存放实现(支持c语言和OC的混编) .mm文件存放实现 (支持OC就和C++的混编) 异常处理,很少被用到/** *#import功能与#include功能一样就是包含文件 ...
- iOS横向瀑布流的封装
前段时间, 做一个羡慕, 需要使用到瀑布流! 说道瀑布流, 或许大家都不陌生, 瀑布流的实现也有很多种! 从scrollView 到 tableView 书写的瀑布流, 然后再到2012年iOS6 苹 ...
- ubuntu更换内核版本
一 详细的使用方法见: http://www.xlgps.com/article/310954.html 二 补充: 1 需要删除旧的内核的方法: sudo apt-get remove linux- ...
- iOS核心笔记—MapKit框架-基础
1.MapKit框架简介: ✨了解:MapKit框架使用须知:①.MapKit框架中所有的数据类型的前缀都是MK:②.需要导入#import <MapKit/MapKit.h>头文件:③. ...
- Wireshark网络抓包(四)——工具
一.基本信息统计工具 1)捕获文件属性(Summary) 1. File:了解抓包文件的各种属性,例如抓包文件的名称.路径.文件所含数据包的规模等信息 2. Time:获悉抓包的开始.结束和持续时间 ...
- Mysql数据库连接查询
Mysql数据库连接查询 连接是关系数据库模型的主要特点.连接查询是关系数据库中最主要的查询,主要包括内连接.外连接等.通过连接运算可以 ...
- linux系统盘使用率达到100%的问题查找和解决方法
今天公司云服务器报警系统发来短信,系统磁盘空间不够,登录服务器进行查看,磁盘使用虑达到100%, 感觉比较奇怪,所存的东西并不多,怎么会将磁盘占满,而且数据都是存在数据盘下,通过简单的进行 ...
- Jenkins学习——Jenkins是什么
Jenkins是什么 对于Jenkins是什么,百度百科给的答案是这样的:Jenkins是一个开源软件项目,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能. 通过这句话,我们可以得到这样的一 ...