Node.js的socket通信和C++、Java的非常相像,学过这两种语言的socket通信的同学可以很快就掌握好Node.js的socket通信。下面我们以实现一个Echo服务器的服务端和客户端为目的,学习一下Node.js的socket通信。
所谓的Echo服务器指的是这样一种服务器:客户端发送一条消息给服务端,服务端就把这条消息原封不动地返回给客户端。
服务端
服务端的实现分为三步:
- 通过createServer创建一个server服务端
- 使用server的listen方法监听指定端口,等待客户端接入
- 通过socket对象来监听data、close等事件,用以完成与客户端的交互
下面是服务端代码:
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 1/**
2 * Created by Administrator on 2015/9/8.
3 */
4
5var net = require('net');
6// 服务器IP
7var HOST = '127.0.0.1';
8// 端口号
9var PORT = 7001;
10
11// 创建一个TCP服务器实例,调用listen函数开始监听指定端口
12// 传入net.createServer()的回调函数将作为”connection“事件的处理函数
13// 在每一个“connection”事件中,该回调函数接收到的socket对象是唯一的
14net.createServer(function(sock) {
15
16 // 获得了一个socket连接,将客户端输出来
17 console.log('CONNECTED: ' +
18 sock.remoteAddress + ':' + sock.remotePort);
19
20 // 为这个socket实例添加一个"data"事件处理函数
21 sock.on('data', function(data) {
22 console.log('DATA ' + sock.remoteAddress + ': ' + data);
23 // 回发该数据,客户端将收到来自服务端的数据,实现ECHO服务器
24 sock.write('' + data );
25 });
26
27 // 为这个socket实例添加一个"close"事件处理函数
28 sock.on('close', function(data) {
29 console.log('CLOSED: ' +
30 sock.remoteAddress + ' ' + sock.remotePort);
31 });
32
33}).listen(PORT, HOST);
34
35console.log('Server listening on ' + HOST +':'+ PORT);
36
37
使用createListener的时候会传入一个回调函数,当客户端连接上服务端时调用。在回调函数里,完成了对data、close事件的监听。
- data事件:当客户端有消息发送过来时触发此事件
- close事件:当客户端断开连接时触发此事件
客户端
因为要实现的是Echo服务器,所以自然要实现输入与输出,这里,我使用了上一篇介绍的Readline模块来实现控制台的输入与输出,对这一模块不太熟悉的同学,可以先去看一下Readline模块的介绍。
与服务端相似,客户端的实现也分为三步:
- 创建一个socket
- 连接上指定IP指定端口号的服务端
- 监听data、close等事件完成与服务端的交互
客户端代码如下:
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 1/**
2 * Created by Administrator on 2015/9/8.
3 */
4
5var net = require('net');
6var readline = require('readline');
7
8// 创建Readline接口
9rl = readline.createInterface(process.stdin, process.stdout);
10
11var HOST = '127.0.0.1';
12var PORT = 7001;
13
14var client = new net.Socket();
15client.connect(PORT, HOST, function() {
16 console.log('CONNECTED TO: ' + HOST + ':' + PORT);
17 // 连接建立后,开始执行命令行输入
18 rl.setPrompt('Test> ');
19 rl.prompt();
20});
21
22// 为客户端添加“data”事件处理函数
23// data是服务器发回的数据
24client.on('data', function(data) {
25 // 输出服务器端传来的消息
26 console.log(""+data);
27 rl.prompt();
28});
29
30// 为客户端添加“close”事件处理函数
31client.on('close', function() {
32 console.log('Connection closed');
33 process.exit(0);
34});
35
36rl.on('line', function(line) {
37 switch(line.trim()) {
38 case 'close':
39 rl.close();
40 return;
41 }
42 client.write(line.trim());
43 rl.prompt();
44}).on('close', function() {
45 console.log('Good bye!');
46 client.end();
47});
48
49
这里应该注意,客户端socket监听了data和close事件、我们的输入输出模块也监听了它们自己的line、close事件,前者是client变量,后者是rl变量,要区别开来。
当我们输入close后,会发生以下过程
- line事件里调用Readline.close()触发了Readline的close事件;
- 在Readline的close事件里,调用client.end()结束客户端,从而触发客户端的close事件;
- 客户端的close事件监听器里执行程序退出操作 process.exit(0).
通信结果
客户端:
服务端:
通信涉及三个过程:
- 客户端接收用户输入信息后将发往服务端;
- 服务端接收客户端传来信息后将原封返回给客户端;
- 客户端接收服务端信息后将其显示出来。
这里只是简单介绍了一下Node.js的基本的用法,如果想要了解更多用法,可以看官方的API文档。