7.1 TCP链接
i> TCP服务器 与 socket 端口对象
var net = require('net'); var file = require('fs').createWriteStream('./a.txt'); // 或者 server = net.createServer((socket) => {}) var server = net.createServer(); server.maxConnections = 10; // 设置TCP最大连接数 console.log('TCP服务器的最大连接个数为:%d', server.maxConnections); server.on('connection', (socket) => { console.log('客户端与服务端链接已建立'); address = socket.address(); // 新客户端连上时显示,用来读取客户端发送的流数据 console.log('socket端口对象的地址信息是%j', address); // socket端口对象的地址信息是{"address":"127.0.0.1","family":"IPv4","port":999} socket.setEncoding('utf8'); // 连接上,发送什么,可以实时接收到 socket.on('data', (data) => { // 设置了 setEncoding,否则 console.log(data.toString()); console.log(data); console.log('已经接收到%d字节的数据', socket.bytesRead); }); // 暂停 socket 的 data 事件的触发,此时数据暂存在一个单独的缓存区中 // 激活是 socket.resume(); // 作用是限制对某个或多个客户端的读取速度,只是暂时放在一个单独的缓存区中 socket.pause(); // 将客户端传入的数据写入到文件 socket 对象的 pipe方法 // 当客户端主动断开时,可以先不关闭,等着触发一个 end 事件 // 取消写入是 socket.unpipe(file) socket.pipe(file, { end: false }); // 客户端主动关闭 socket.on('end', () => { console.log('客户端连接被关闭'); // 触发该 end 事件 file.end('再见'); }); socket.setTimeout(10 * 1000); socket.on('timeout', () => { console.log('10秒内无新的交互,已超时'); // 既只执行一次 取消再次触发该事件 socket.setTimeout(0); }); }); server.getConnections((err, count) => { console.log('当前存在%d个客户端连接', count); }); // error 是写死的 server.on('error', (e) => { if (e.code == 'EADDRINUSE') { console.log('服务器地址和端口被占用'); }; }); server.close(() => { console.log('TCP服务器被关闭'); }); // 此时可以 telnet 127.0.0.1 999 连接测试 server.listen(999, '127.0.0.1', () => { console.log('服务器开始监听'); address = server.address(); console.log('被监听的地址信息为:%j', address); // 被监听的地址信息为:{"address":"127.0.0.1","family":"IPv4","port":999 });
i> 创建TCP客户端
服务端:
var net = require('net'); var server = net.createServer(); var fs = require('fs'); // 建立TCP服务器 server.on('connection', (socket) => { console.log('客户端与服务端连接已建立'); socket.setEncoding('utf8'); socket.setKeepAlive(true, 5000); // 将文件内容发送过去 // readStream 读取文件流,将读取的内容放到队列缓冲区中 // 然后 socket.write 从队列缓冲区中拿数据发送 var readStream = fs.createReadStream('./a.txt'); readStream.on('data', (data) => { var flag = socket.write(data); // 如果一次性发不完,则 flag 为 false,否则为 true console.log('发送文件内容的返回值' + flag); console.log('缓存队列缓存了%d字节的字符', socket.bufferSize); }); // 每当有新的连接进来,都会执行这里 // 当前接收的客户端连接数为2时,拒绝新的客户端请求 server.getConnections((err, count) => { console.log('现在客户端连接数量是:%d', count); if (count == 2) server.close(); // 与服务器连接发生了错误,错误码为ECONNREFUSED }); socket.on('data', (data) => { console.log('接收到客户端发送的数据:' + data); // socket.write('你好,Client'); }); // 缓冲区 有数据 => 没数据 socket.on('drain', () => { console.log('TCP缓冲区的数据已经全部发送'); }); // 客户端 crtl + c 掉 socket.on('error', (err) => { console.log('与客户端通信发生了一个错误,错误码是:%s', err.code); // 与客户端通信发生了一个错误,错误码是:ECONNRESET // destroy 销毁端口对象,确保端口不会再被利用 socket.destroy(); server.close(); }); // 客户端调用了 end 方法主动关闭之后 // 此时 服务端仍然未关闭 socket.on("end", () => { console.log('客户端连接被关闭'); // 自己也主动关闭 // 之后也可以用,server.ref() 方法阻止应用程序的关闭 server.unref(); }); // 试着打开/ 关闭 客户端的 end事件,使用 ctrl + c 查看 // 如果客户端自己正常 end ,则不会有 had_error 错误 socket.on('close', (had_error) => { if (had_error) { console.log('由于一个错误导致socket端口被关闭'); socket.unref(); } else { console.log('socket端口正常关闭'); } }); }); server.on('close', () => { console.log('关闭TCP服务器'); }); server.listen(999, '127.0.0.1');
客户端:
var net = require('net'); var client = new net.Socket(); client.setEncoding('utf8'); // TCP 客户端 client.connect(999, '127.0.0.1', () => { console.log('已经连接到服务端'); client.write('你好,Server'); console.log('当前已经发送%d字节的数据', client.bytesWritten); setTimeout(() => { // end 方法关闭与服务端的链接 client.end('10秒后我主动断开,再见'); console.log('当前已经发送%d字节的数据', client.bytesWritten); }, 10 * 1000); }); client.on('data', (data) => { console.log('收到服务端发送的数据:' + data); }); client.on('error', (err) => { console.log('与服务器连接发生了错误,错误码为%s', err.code); client.destroy(); });
i> net 模块中的类和方法