1. 创建简易TCP服务端
var net = require('net');
var server = net.createServer();
server.on('connection', function(socket){
socket.write("欢迎光临《深入浅出Node.js》示例:\n");
});
server.on('end', function () {
console.log('连接断开');
});
server.listen(8124, function () {
console.log('server bound');
});
2.创建与客户端交互的TCP服务端: server.js
var net = require('net');
var server = net.createServer(function (socket) {
// 新的连接
socket.on('data', function (data) {
console.log("from client:", data.toString());
socket.write("你好");
});
socket.on('end', function () {
console.log('连接断开');
});
socket.write("欢迎光临《深入浅出Node.js》示例:\n");
});
server.listen(8124, function () {
console.log('server bound');
});
3. 创建客户端: client.js
var net = require('net');
var client = net.connect({port: 8124}, function () { //'connect' listener
console.log('client connected');
client.write('world!\r\n');
});
client.on('data', function (data) {
console.log("from server:", data.toString());
client.end();
});
client.on('end', function () {
console.log('client disconnected');
});
4. 执行结果
首先启动服务器端,然后启动客户端,结果如下
xiao@uXiao:~/nodejs/深入浅出nodejs/chapter7$ node server.js
server bound
from client: world!
连接断开
xiao@uXiao:~/nodejs/深入浅出nodejs/chapter7$ node client.js
client connected
from server: 欢迎光临《深入浅出Node.js》示例:
from server: 你好
client disconnected
5. TCP服务的事件
在上述的示例中,代码分为服务器事件和连接事件
5.1. 服务器事件
对于通过 net.createServer() 创建的服务器而言,它是一个 EventEmitter 实例,它的自定义事件有如下几种。
- listening :在调用 server.listen() 绑定端口或者Domain Socket后触发,简洁写法为server.listen(port,listeningListener) ,通过 listen() 方法的第二个参数传入。
- connection :每个客户端套接字连接到服务器端时触发,简洁写法为通过 net.create-Server() ,最后一个参数传递。
- close :当服务器关闭时触发,在调用 server.close() 后,服务器将停止接受新的套接字连接,但保持当前存在的连接,等待所有连接都断开后,会触发该事件。
- error :当服务器发生异常时,将会触发该事件。比如侦听一个使用中的端口,将会触发一个异常,如果不侦听 error 事件,服务器将会抛出异常。
5.2. 连接事件
服务器可以同时与多个客户端保持连接,对于每个连接而言是典型的可写可读 Stream 对象。Stream 对象可以用于服务器端和客户端之间的通信,既可以通过 data 事件从一端读取另一端发来的数据,也可以通过 write() 方法从一端向另一端发送数据。它具有如下自定义事件。
- data :当一端调用 write() 发送数据时,另一端会触发 data 事件,事件传递的数据即是write() 发送的数据。
- end :当连接中的任意一端发送了 FIN 数据时,将会触发该事件。
- connect :该事件用于客户端,当套接字与服务器端连接成功时会被触发。
- drain :当任意一端调用 write() 发送数据时,当前这端会触发该事件。
- error :当异常发生时,触发该事件。
- close :当套接字完全关闭时,触发该事件。
- timeout :当一定时间后连接不再活跃时,该事件将会被触发,通知用户当前该连接已经被闲置了。
6. Nagle算法
TCP针对网络中的小数据包有一定的优化策略:Nagle算法。如果每次只发送一个字节的内容而不优化,网络中将充满只有极少数有效数据的数据包,将十分浪费网络资源。Nagle算法针对这种情况,要求缓冲区的数据达到一定数量或者一定时间后才将其发出,所以小数据包将会被Nagle算法合并,以此来优化网络。这种优化虽然使网络带宽被有效地使用,但是数据有可能被延迟发送。
在Node中,由于TCP默认启用了Nagle算法,可以调用 socket.setNoDelay(true) 去掉Nagle算法,使得 write() 可以立即发送数据到网络中。
另一个需要注意的是,尽管在网络的一端调用 write() 会触发另一端的 data 事件,但是并不意味着每次 write() 都会触发一次 data 事件,在关闭掉Nagle算法后,另一端可能会将接收到的多个小数据包合并,然后只触发一次 data 事件。