在《构建TCP服务》的示例中,代码分为服务器事件和连接事件。
1. 服务器事件
对于通过net.createServer()
创建的服务器而言,他是一个EventEmitter
实例,它的自定义事件有如下几种:
-
listening:在调用
server.listen()
绑定端口或者Domain Socket
后触发,简介写法为server.listen(port,listeningListener
),回调通过listen()方法的得第二个参数传入。
server.listen(port, function(){
console.log('listening触发!');
});
-
connection: 每个客户端套接字连接到服务器端时(
新的连接建立
)触发,简介写法为通过net.createServer()
,最后一个参数传递。
const server = net.createServer((c) => {
// 'connection' 监听器。
console.log('connection,客户端已连接');
);
- close:当服务器关闭时触发,在调用server.close()后,服务器将停止接受新的套接字链接,单保持当前存在的链接,等待所有链接都断开后,会触发该事件。
- error:当服务器发生异常时,将会触发该事件,比如侦听一个使用中的端口,将会触发一个异常,如果不侦听异常事件,服务器将抛出异常。
server.on('error', (err) => {
console.log(err);
});
2. 连接事件
服务器可以同时与多个客户端保持连接,对于每个连接而言是典型的可写可读Stream
对象。Stream
对象可以用于服务器端和客户端之间的通信,既可以通过data事件从一端读取另一端发来的数据,也可以通过write()方法从另一端发送数据。它具有如下自定义事件。
-
data:当一端调用
write()
发送数据时,另一端会触发data
事件,事件传递的数据既是write()
发送的数据。 -
end:当连接中的任意一端发送了FIN(
TCP中
SYN指的是请求建立链路、
ACK指的是应答、而这里的
FIN指的是终止当前链路
)数据时,将会触发该事件。 - connect:该事件用于客户端,当套接字(socket)与服务器端连接成功时会被触发。
- drain:当任意一端调用write()发送数据时,当前这端会触发该事件。
- error:当异常发生时,会触发该事件。
- close:当套接字(socket)完全关闭时,触发该事件。
- timeout:当一定事件后连接不在活跃时,该事件将会被触发,通知用户当前该连接已经被闲置了。
3. Nagle算法。
由于TCP套接字(socket)是可写可读的stream
对象,可以利用pipe()
方法巧妙地实现管道操作,下面代码实现echo服务器:
var net = require('net');
var server = net.createServer(function (socket) {
socket.write('Echo server\r\n');
socket.pipe(socket);
});
server.listen(1337, '127.0.0.1')
TCP针对网络中的小数据包有一定的优化策略:Nagle
算法。
如果每次只发送一个字节的内容而不优化,网络中将充满只有极少数有效数据的数据包,将十分浪费网络资源。
Nagle
算法针对这种情况,要求缓冲区的数据达到一定数量或者一定事件后才将其发出,所以小数据包将会被Nagle
算法合并,以此来优化网络。这种优化虽然使网络宽带被有效地使用,但是数据有可能被延迟发送。
在node中TCP默认启用了
Nagle
算法,可以调用socket.setNoDelay(true)
;去掉Nagle
算法,使得write()
可以立即发送数据到网络中。
需要注意的是,尽管在网络的一端调用
write()
会触发另一端的data事件,但是并不意味着每次调用write()
都会触发一次data
事件,在关闭掉Nagle
算法后,另一端可能会将多个小数据包合并,然后触发一次data
事件。
网友评论