前言: 在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创建一个服务,该方法中参数为一个回调函数,符合事件驱动概念,该回调函数中的参数为connection对象,咱们就使用该对象进行net.stream数据流的传递
滤清思路后,我们开始:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const net = require ('net' );
let server = net.createServer(function (conn ) {
};
在上述代码中,我们创建了一个server服务器,接下来我们思考,我们的服务器需要对端口进行监听:
const net = require ('net' );
let server = net.createServer(function (conn ) {
};
server.listen(3000 , function ( ) {
console .log('\033[96m server listening on *:3000\033[39m' );
});
监听端口号为3000,当我们启动服务器时,可以在终端中显示: (保留)
接下来我们尝试用telnet客户端连接咱们刚搭建好的服务器:(保留)
*Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主要方式
*若您不知道如何打开telnet,请阅读——https://zhidao.baidu.com/question/689801449777342884.html
那么,我们在telnet客户端界面看到,目前没有任何显示,所以我们需要去设计一个用户使用的界面:
效果如图:(保留)
我们考虑:如何在终端上显示提示符?
connection对象上提供了write方法,可以在通过连接的客户端上显示输入内容,所以我们在server对象内部设计用户界面:1
2
3
4
5
6
7
8
let server = net.createServer(function (conn ) {
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对象对输入数据注册事件:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let count = 0 ;
let server = net.createServer(function (conn ) {
count++;
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参数就是用户输入的数据了,不过我们考虑,用户首先输入的应该是用户名,其次才是聊天数据,所以我们应该:
1.用列表对用户名进行保存
2.判断用户名是否第一次输入信息,以便重新注册
3.判断用户输入昵称是否已存在1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
let count = 0 ;
let users = {};
let server = net.createServer(function (conn ) {
count++;
let nickname;
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;
}
} else {
for (var i in users) {
if (i != nickname) {
console .log('\033[96m > ' + nickname + ':\033[39m ' + data + '\n' );
}
}
}
}
};
实现后效果:(保留)
当用户关闭客户端时,我们不想保存用户名,我们可以注册close事件:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let count = 0 ;
let users = {};
let server = net.createServer(function (conn ) {
count++;
let nickname;
conn.on('close' , function ( ) {
count--;
console .log('\033[90m > ' + nickname + ' left the room\033[39m\n' );
delete users[nickname];
});
};
到目前为止,我们已经实现了整个聊天程序的功能,那么我们应该思考代码重构:
我们在用户接入与断开连接时,都写入了提示信息,那么,我们应该将提示信息抽离出来,作为一个广播函数:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
let count = 0 ;
let users = {};
let server = net.createServer(function (conn ) {
count++;
let nickname;
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;
users[nickname] = conn;
broadcast('\033[90m > ' + nickname + ' joined the room\033[39m\n' );
}
} else {
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];
});
};
至此,我们的整个聊天程序就大功告成了!
大家可以在我的github上获取源码——https://github.com/TimRChen/NodeCLI-telnet
相应操作文档——click here!