本文深入解析Node.js中net模块的核心API,涵盖基于流的TCP与IPC网络通信。详细阐述net.createServer()与net.createConnection()的用法,解析net.Server与net.Socket类的关键属性与方法,包括连接管理、数据流控制及事件处理,并提供完整代码示例,帮助开发者构建高效的网络应用。
本文通过具体实例深入解析Node.js中的net模块,旨在为开发者提供实用的参考与指导。
Node.js net模块API详解
net模块提供了创建基于流的TCP或IPC服务器(使用net.createServer())和客户端(使用net.createConnection())的异步网络API。
引入方式如下:
const net = require('net');
net.isIP(input)
功能说明:
用于测试input是否为IP地址。若输入字符串无效,返回0;若是IPv4地址,返回4;若是IPv6地址,返回6。
示例代码:
const net = require('net');
console.log( net.isIP('127.0.0.1') );
// 4
net.isIPv4(input)
功能说明:
若input是IPv4地址,返回true;否则返回false。
示例代码:
const net = require('net');
console.log( net.isIPv4('127.0.0.1') );
// true
net.isIPv6(input)
功能说明:
若input是IPv6地址,返回true;否则返回false。
示例代码:
const net = require('net');
console.log( net.isIPv6('127.0.0.1') );
// false
net.createServer([options][, connectionListener])
功能说明:
创建一个新的TCP或IPC服务。 options参数说明: allowHalfOpen:表示是否允许半开的TCP连接。默认值为false。 pauseOnConnect:连接建立后是否暂停套接字。默认值为false。 connectionListener:自动为事件设置监听器。 若allowHalfOpen设置为true,当socket.end()被显式调用时,服务端仅返回一个FIN数据包,连接将处于半闭状态(不可读但可写)。 若pauseOnConnect设置为true,与连接相关的套接字将暂停,且不会从套接字句柄读取数据。这允许连接在进程间传递,避免被初始进程读取。如需从暂停的套接字读取数据,请调用socket.resume()。 该服务可以是TCP服务或IPC服务,具体取决于listen()监听的目标。
示例代码:
const net = require('net');
const server = net.createServer((c) => {
c.write('hello\r\n');
c.pipe(c);
});
server.listen(8124, () => {
console.log('server bound');
});
net.createConnection()
功能说明:
这是一个用于创建net.Socket的工厂函数,它会立即使用socket.connect()初始化连接,并返回启动连接的net.Socket。 连接建立后,返回的socket上将触发'connect'事件。 若指定了最后一个参数connectListener,它将被添加为'connect'事件的监听器。 注意:net.connect()函数也是该函数的别名。
net.createConnection(options[, connectListener])
功能说明:
与net.createConnection()功能一致。 connectListener:若传递该参数,将被添加为返回socket上的'connect'事件监听器。 注意:net.connect(options[, connectListener])函数也是该函数的别名。
示例代码:
const net = require('net');
const client = net.createConnection({ port: 8124 }, () => {
//'connect' listener
console.log('connected to server!');
client.write('world!\r\n');
});
client.on('data', (data) => {
console.log(data.toString());
client.end();
});
client.on('end', () => {
console.log('disconnected from server');
});
// 如果要连接到 /tmp/echo.sock,第二行只需要改为:
const client = net.createConnection({ path: '/tmp/echo.sock' });
net.createConnection(path[, connectListener])
功能说明:
初始化一个IPC连接。 该方法使用所有默认选项创建一个新的net.Socket, 使用socket.connect(path[, connectListener])立即初始化连接,然后返回初始化连接的net.Socket。 path:Socket应该被连接到的路径。 注意:net.connect(path[, connectListener])函数也是该函数的别名。
net.createConnection(port[, host][, connectListener])
功能说明:
初始化一个TCP连接。 这个函数用默认配置创建一个新的net.Socket, 然后socket.connect(port[, host][, connectListener])初始化一个连接,并返回开启连接的那个net.Socket。 注意:net.connect(port[, host][, connectListener])函数也是该函数的别名。
net.Server类
功能说明:
这个类用于创建TCP或IPC服务器。
new net.Server([options][, connectionListener])
功能说明:
创建一个net.Server实例。 与net.createServer([options][, connectionListener])功能一致
示例代码:
const net = require('net');
const server = new net.Server((c) => {
// 'connection' listener
c.write('hello');
});
server.on('error', (err) => {
throw err;
});
server.listen(8124, () => {
console.log('server bound');
});
server.listen()
功能说明:
为connections启动一个server监听。 一个net.Server可以是TCP服务器或IPC服务器,具体取决于它监听的内容。 可能的参数: server.listen(handle[, backlog][, callback]) server.listen(options[, callback]) server.listen(path[, backlog][, callback]) 用于IPC服务器 server.listen([port][, host][, backlog][, callback]) 用于TCP服务器 该函数是异步的。当server开始监听时,'listening'事件会被触发。 最后一个参数callback将被添加为'listening'事件的监听器。 监听时,常见的错误是EADDRINUSE。这是因为另一个server已经监听了该请求中的port/path/handle。
server.listen(handle[, backlog][, callback])
功能说明:
启动一个服务器,监听已经绑定到端口、UNIX域套接字或Windows命名管道的给定句柄上的连接。 句柄对象可以是服务器、套接字(任何具有底层_handle成员的东西), 也可以是具有fd成员的对象,该成员是一个有效的文件描述符。 注意:在Windows上不支持在文件描述符上进行监听。
server.listen(options[, callback])
功能说明:
启动一个TCP服务监听输入的port和host。 options:必须。支持以下参数属性: port:端口 host:主机 path:如果指定了port参数则会被忽略。 如果指定了port参数,该方法的行为跟server.listen([port][, hostname][, backlog][, callback])一样。 否则,如果指定了path参数,该方法的行为与server.listen(path[, backlog][, callback])一致。 如果没有port或者path参数,则会抛出一个错误。
server.listen(path[, backlog][, callback])
功能说明:
启动一个IPC服务器监听给定path的连接。 path:服务器需要监听的路径
server.listen([port][, host][, backlog][, callback])
功能说明:
启动一个TCP服务监听输入的port和host。 如果port省略或是0,系统会随意分配一个在'listening'事件触发后能被server.address().port检索的无用端口。
server.listening
功能说明:
一个布尔值,表明server是否正在监听连接
示例代码:
const net = require('net');
const server = new net.Server((c) => {
// 'connection' listener
c.write('hello');
});
server.on('error', (err) => {
throw err;
});
server.listen(8124, () => {
console.log(server.listening);
});
// true
listening事件
功能说明:
当服务被绑定后调用
示例代码:
const net = require('net');
const server = new net.Server((c) => {
// 'connection' listener
c.write('hello');
});
server.on('listening', () => {
console.log('开始监听');
});
server.listen(8124, () => {
console.log(server.listening);
});
// 开始监听
server.address()
功能说明:
如果在IP socket上监听,则返回绑定的ip地址、地址族和操作系统报告的服务端口。 在找到操作系统分配的地址时,找到指定的端口是有用的。 返回一个有port、family和address属性的对象:{ port: 12346, family: 'IPv4', address: '127.0.0.1' } 对于在管道或UNIX域套接字上侦听的server,该名称将返回为字符串。 只有到了'listening'事件被触发时候,才可以调用server.address()。
示例代码:
const net = require('net');
const server = new net.Server((c) => {
// 'connection' listener
c.write('hello');
});
server.on('error', (err) => {
throw err;
});
server.listen(8124, () => {
console.log('opened server on', server.address());
});
// opened server on { address: '::', family: 'IPv6', port: 8124 }
server.maxConnections
功能说明:
设置该属性使得当server连接数过多时拒绝连接。 一旦将一个socket发送给child_process.fork()生成的子进程,就不推荐使用该选项。
示例代码:
const net = require('net');
const server = new net.Server((c) => {
// 'connection' listener
c.write('hello');
});
server.maxConnections = 10;
server.listen(8124, () => {
console.log(server.listening);
});
server.getConnections(callback)
功能说明:
异步获取服务器的当前并发连接数。当socket被传递给子进程时工作。 回调函数的两个参数是err和count。
示例代码:
const net = require('net');
const server = new net.Server((c) => {
// 'connection' listener
c.write('hello');
});
server.getConnections((err, count) => {
console.log(count);
});
server.listen(8124, () => {
console.log(server.listening);
});
// 0
server.connections(已废弃)
功能说明:
获取服务器的当前并发连接数。
connection事件
功能说明:
当一个新的connection建立的时候触发。传递一个net.Socket的实例对象。
示例代码:
const net = require('net');
const server = new net.Server((c) => {
// 'connection' listener
c.write('hello');
});
server.on('connection', (socket) => {
console.log(socket);
});
server.listen(8124, () => {
console.log(server.listening);
});
server.unref()
功能说明:
如果这个server在事件系统中是唯一有效的,那么对server调用unref将允许程序退出。 如果这个server已经调用过unref,那么再次调用将不会再有效果。
server.ref()
功能说明:
在一个已经调用unref的server中调用ref,如果server是仅存的server,则程序不会退出(默认)。 对一个已经调用ref的server再次调用ref将不会再有效果。
server.close([callback])
功能说明:
停止server接受建立新的connections并保持已经存在的connections。 此功能是异步的,当所有的connections关闭同时server响应'close'事件的时候,server将会最终关闭。 一旦'close'发生将会调用可选的回调函数。与该事件不同,如果服务器在关闭时未打开,则将使用错误作为唯一参数。
示例代码:
const net = require('net');
const server = new net.Server((c) => {
// 'connection' listener
c.write('hello');
});
server.listen(8124, () => {
console.log(server.listening);
});
server.close();
close事件
功能说明:
当server关闭的时候触发。注意,如果有连接存在,直到所有的连接结束才会触发这个事件。
示例代码:
const net = require('net');
const server = new net.Server((c) => {
// 'connection' listener
c.write('hello');
});
server.on('close', () => {
console.log('server 已关闭')
})
server.listen(8124, () => {
console.log(server.listening);
});
server.close();
// server 已关闭
error事件
功能说明:
当错误出现的时候触发。 不同于net.Socket,'close'事件不会在这个事件触发后继续触发。 除非server.close()是手动调用。在server.listen()中的例子。
示例代码:
const net = require('net');
const server = new net.Server((c) => {
// 'connection' listener
c.write('hello');
});
server.on('error', (err) => {
console.log('发生异常', err);
})
server.listen(8124, () => {
console.log(server.listening);
});
net.Socket类
功能说明:
这个类是TCP或UNIX Socket的抽象(在Windows上使用命名管道,而UNIX使用域套接字)。 一个net.Socket也是一个duplex stream,所以它能被读或写,并且它也是一个EventEmitter。 net.Socket可以被用户创建并直接与server通信。 举个例子,它是通过net.createConnection()返回的,所以用户可以使用它来与server通信。 当一个连接被接收时,它也能被Node.js创建并传递给用户。 比如,它是通过监听在一个net.Server上的'connection'事件触发而获得的,那么用户可以使用它来与客户端通信。
new net.Socket([options])
功能说明:
创建一个socket对象。 options参数说明: fd:如果指定了该参数,则使用一个给定的文件描述符包装一个已存在的socket,否则将创建一个新的socket。 allowHalfOpen:指示是否允许半打开的TCP连接。默认是false。 readable:当传递了fd时允许读取socket,否则忽略。默认false。 writable:当传递了fd时允许写入socket,否则忽略。默认false。 新创建的socket可以是TCP socket也可以是IPC端点流,取决于它连接connect()到什么。
socket.connect()
功能说明:
在给定的套接字上启动一个连接。 该方法是异步的。当连接建立了的时候,'connect'事件将会被触发。 如果连接过程中有问题,'error'事件将会代替'connect'事件被触发,并将错误信息传递给'error'监听器。 最后一个参数connectListener,如果指定了,将会被添加为'connect'事件的。 可能的用法: socket.connect(options[, connectListener]) socket.connect(path[, connectListener]) 用于IPC连接。 socket.connect(port[, host][, connectListener]) 用于TCP。
socket.connect(options[, connectListener])
功能说明:
在给定的socket上初始化一个连接。 通常该方法是不需要的,应该使用net.createConnection()来创建和打开socket。 一般只在实现一个自定义的Socket的时候使用该方法。 对于TCP连接可能的options有: port 必须。Socket连接的端口。 host Socket连接的主机。默认是'localhost'. localAddress Socket连接的本地地址。 localPort Socket连接的本地端口。 family IP栈的版本,可以是4或6。默认值为4。 hints 可选的dns.lookup() hints。 lookup 自定义的lookup方法。默认是dns.lookup(). 对于IPC连接可能的options有: path 必须。客户端连接的路径。
socket.connect(path[, connectListener])
功能说明:
在给定的socket上初始化IPC。 相当使用{path: path}作为options调用socket.connect(options[, connectListener])方法。
socket.connect(port[, host][, connectListener])
功能说明:
在给定的socket上初始化一个TCP连接。 相当于使用{port: port, host: host}作为options调用socket.connect(options[, connectListener])方法。
connect事件
功能说明:
当一个socket连接成功建立的时候触发该事件。
socket.connecting
功能说明:
该属性如果为true,则socket.connect(options[, connectListener])被调用但还未结束。 当发送connect事件或调用socket.connect(options[, connectListener])的回调函数的时候会被设置为false。
close事件
功能说明:
一旦socket完全关闭就发出该事件。 参数had_error是boolean类型,表明socket的关闭是否取决于传输错误。
data事件
功能说明:
当接收到数据的时触发该事件。data参数是一个Buffer或String。 数据编码由socket.setEncoding()设置。 注意:当Socket发送data事件的时候,如果没有监听者数据将会丢失。
drain事件
功能说明:
当写入缓冲区变为空时触发。可以用来做上传节流。
error事件
功能说明:
当错误发生时触发。'close'事件也会紧接着该事件被触发。
lookup事件
功能说明:
在找到主机之后创建连接之前触发。不可用于UNIX socket。 参数: err:错误对象。 address:IP地址 family:地址类型。 host:主机
timeout事件
功能说明:
当socket超时的触发。该事件只是用来通知socket已经闲置。用户必须手动关闭。
socket.address()
功能说明:
返回操作系统报告的socket的地址、地址族和端口。 返回的对象有三个属性,例如:{ port: 12346, family: 'IPv4', address: '127.0.0.1' }
socket.bufferSize
功能说明:
net.Socket具有该属性,socket.write()工作时需要。它可以帮助用户快速启动和运行。 计算机(处理速度)不能总是跟上socket的写入速度——网络连接可能太慢了。 Node.js内部将维护一个写入socket的数据队列,并在可能的时候将数据发送出去。 (内部实现是对socket的文件描述符进行轮询其是否是可写状态。) 使用内部缓冲的结果是可能造成内存的增长。此属性显示当前即将被写入的缓冲的字符数。 (字符串的数目大致等于即将被写入的字节,但缓冲可能包含字符串,而字符串是惰性编码的,所以实际的字节数是不知道的。) 对处理大量或持续增长的bufferSize有经验的用户应该注意使用socket.pause()和socket.resume()对他们程序中的数据流进行节流。
socket.bytesRead
功能说明:
接收的字节数量。
socket.bytesWritten
功能说明:
发送的字节数量。
socket.destroy([exception])
功能说明:
确保在该socket上不再有I/O活动。仅在出现错误的时候才需要(如解析错误等)。 如果制定了exception,则将会触发一个'error'事件,任何监听器都将接收到exception作为一个参数。
socket.destroyed
功能说明:
一个布尔值,用来指示连接是否已经被销毁。一旦连接被销毁就不能再使用它传输任何数据。
socket.end([data][, encoding])
功能说明:
半关闭socket。例如发送一个FIN包。服务端仍可以发送数据。 如果指定了data,则相当于调用socket.write(data, encoding)之后再调用socket.end()。
end事件
功能说明:
当socket的另一端发送一个FIN包的时候触发,从而结束socket的可读端。 默认情况下(allowHalfOpen为false),socket将发送一个FIN数据包, 并且一旦写出它的等待写入队列就销毁它的文件描述符。 当然,如果allowHalfOpen为true,socket就不会自动结束end()它的写入端,允许用户写入任意数量的数据。 用户必须调用end()显示地结束这个连接(例如发送一个FIN数据包。)
socket.localAddress
功能说明:
远程客户端连接的本地IP地址字符串。 例如,一个服务端正在连接到'0.0.0.0',客户端连接到的是'192.168.1.1',则socket.localAddress的值是'192.168.1.1'。
socket.localPort
功能说明:
用数字表示的本地端口。例如80或21。
socket.pause()
功能说明:
暂停读写数据。也就是说,'data'将不会再被触发。可以用于上传节流
socket.resume()
功能说明:
在调用socket.pause()之后恢复读取数据。
socket.unref()
功能说明:
如果活跃的socket是事件系统中仅存的socket,则调用unref将会允许程序退出。 对一个已经调用了unref的socket再调用unref无效。
socket.ref()
功能说明:
与unref相反,在一个已经调用unref的socket中调用ref, 如果socket是仅存的socket,则程序不会退出(默认)。对一个已经调用ref的socket再次调用ref将不会再有效果。
socket.remoteAddress
功能说明:
用字符串表示的远程IP地址。例如'74.125.127.100'或'2001:4860:a005::68'。 如果socket被销毁了(如客户端已经失去连接)则其值为undefined。
socket.remoteFamily
功能说明:
用字符串表示的远程IP协议族。'IPv4'或'IPv6'。
socket.remotePort
功能说明:
用数字表示的远程端口。例如80或21。
socket.setEncoding([encoding])
功能说明:
设置作为可读流(Readable Stream)的编码。
socket.setKeepAlive([enable][, initialDelay])
功能说明:
启用/禁用长连接功能,并且在第一个长连接探针被发送到一个空闲的socket之前可选则配置初始延迟。enable默认为false。 initialDelay(毫秒)用来设置接收到最后一个数据包和发送第一个长连接探针之间的延迟。 将initialDelay设置为0,则会保持默认值(或之前设置的值)不变。默认是0。
socket.setNoDelay([noDelay])
功能说明:
禁止Nagle。默认情况下TCP连接使用Nagle算法,在发送之前缓冲数据。 将noDelay设置为true将会在每次socket.write()被调用的时候立即发送数据。noDelay默认是true。
socket.setTimeout(timeout[, callback])
功能说明:
当socket在timeout毫秒不活动之后将其设置为超时状态。默认net.Socket没有超时。 当一个闲置的超时被触发,socket将会收到一个'timeout'事件,但连接不会被断开。 用户必须手动调用socket.end()或socket.destroy()来断开连接。 如果timeout是0,则存在的闲置超时将会被禁止。 可选的callback参数将会被当作一个时间监听器被添加到'timeout'事件。
socket.write(data[, encoding][, callback])
功能说明:
在socket上发送数据。第二个参数制定了字符串的编码——默认是UTF8编码。 如果全部数据都成功刷新到内核的缓冲则返回true。 如果全部或部分数据在用户内中排队,则返回false。当缓冲再次空闲的时候将触发'drain'事件。 当数据最终都被写出之后,可选的callback参数将会被执行——可能不会立即执行。
希望本文所述对大家node.js程序设计有所帮助。