我作为一个初学者,在看书写代码的时候难免会遇到一些坑,我想把自己经历的大大小小的一些坑写出来。不仅提醒自己,也是给同处相同学习阶段的人的小小的分享。
这几天看了看node.js的net
模块,看到了socket
对象监听data
事件以及socket
对象的pipe
方法。
我误以为pipe
方法就是将socket
对象监听data
事件时返回的data
数据写入文件。于是我写了如下代码:
let net = require('net');
let fs = require('fs');
let tcpServer = net.createServer();
tcpServer.on('listening', ()=>{
console.log('开始监听');
});
tcpServer.on('connection', (socket)=>{
console.log('连接已建立' + '\n');
tcpServer.getConnections((err, count)=>{
if(err){
console.warn(err);
} else {
console.log(`当前有${count}个连接`);
}
});
let writeStream = fs.createWriteStream('./message.txt');
socket.on('data', (data)=>{
socket.pipe(writeStream);
});
});
tcpServer.listen(2000);
上面的代码中我用net
模块的createServer
方法创建了一个TCP服务器,可以看到在socket
对象对data
事件的监听函数中,执行的是socket.pipe(writeStream);
。
当连接建立后,我在客户端键盘输入"12345"之后,在message.txt
里写入的却是2334445555
。
而按多几个键之后则会出现达到监听器的最大上限和内存泄露的错误提示。
这一开始让我百思不得其解,明明我按的是"12345",为什么输出的文件中没有1
?为什么有两个“3”,三个“4”和四个“5”?还有为什么按多几个键之后就会报错?
后来我注意到书上有这么一句话
可以利用socket对象的pipe方法将客户端发送的流数据书写到文件等其他目标对象中。
我突然意识到是不是直接使用pipe方法就可以了呢?于是我就把socket
对象对data
事件的监听去掉:
let net = require('net');
let fs = require('fs');
let tcpServer = net.createServer();
tcpServer.on('listening', ()=>{
console.log('开始监听');
});
tcpServer.on('connection', (socket)=>{
console.log('连接已建立' + '\n');
tcpServer.getConnections((err, count)=>{
if(err){
console.warn(err);
} else {
console.log(`当前有${count}个连接`);
}
});
let writeStream = fs.createWriteStream('./message.txt');
socket.pipe(writeStream);
});
tcpServer.listen(2000);
运行的结果一切都正常。
原来,pipe
方法的实现本身就监听了data
、end
等事件。所以,当我按下"1"的时候,pipe
方法才刚开始监听,自然"1"也就不会被写入到文件中,而我按下“2”之后,“2”被写入文件,而这时候又会多一条通往被写入文件的管道,同时也增加了一系列的监听函数。
于是我按下“3”的时候,“3”就会通过两个管道被写入文件,也就出现了两个“3”。而这时候,也会再多一条通往被写入文件的管道。
这就是之前种种奇怪现象的原因。当按的键足够多,达到系统默认的一个对象可以设置监听器的最大值时,就会报错。