NodeJS之net模块

2019/8/28 NodeJS

🌙 NodeJS之net模块学习笔记

🌙 1.net(网络)模块简介

net 模块用于创建基于流(stream-based)的 TCP 或 IPC (opens new window) 的服务器(net.createServer() (opens new window))与客户端(net.createConnection() (opens new window))。

使用方法如下:

const net = require('net');
1

🌙 2.net.Server 类

此类用于创建 TCP 或 IPC (opens new window) 服务器。

🌙 2.1 new net.Server([options][, connectionListener])构造函数

net.Server 是一个 EventEmitter (opens new window),实现了以下事件:

事件名称 说明
close 当 server 关闭的时候触发。 如果有连接存在,直到所有的连接结束才会触发这个事件。
connection 当一个新的连接建立的时候触发。 socket 是一个 net.Socket 实例。
error 当错误出现的时候触发。 不同于 net.Socket (opens new window)'close' (opens new window) 事件不会在这个事件触发后继续触发,除非 server.close() (opens new window) 是手动调用。 参见 server.listen() (opens new window) 中的例子。
listening 当调用 server.listen() (opens new window) 绑定服务器之后触发。

🌙 2.2 server.listen()

启动一个服务器来监听连接。 net.Server 可以是 TCP 或 IPC (opens new window) 服务器,具体取决于它监听的内容。

可能的参数:

这个函数是异步的。当服务器开始监听时,会触发 'listening' (opens new window) 事件。 最后一个参数 callback 将被添加为 'listening' (opens new window) 事件的监听器。

所有的 listen() 方法都可以使用一个 backlog 参数来指定待连接队列的最大长度。 此参数的默认值是 511 (不是512)。

所有的 net.Socket (opens new window) 都被设置为 SO_REUSEADDR (详见 socket(7) (opens new window))。

当且仅当上次调用 server.listen() 发生错误或已经调用 server.close() 时,才能再次调用 server.listen() 方法。否则将抛出 ERR_SERVER_ALREADY_LISTEN 错误。

监听时最常见的错误之一是 EADDRINUSE。 这是因为另一个服务器已正在监听请求的 port/path/handle。 处理此问题的一种方法是在一段时间后重试:

server.on('error', (e) => {
  if (e.code === 'EADDRINUSE') {
    console.log('地址正被使用,重试中...');
    setTimeout(() => {
      server.close();
      server.listen(PORT, HOST);
    }, 1000);
  }
});
1
2
3
4
5
6
7
8
9

🌙 2.3 server.address()

如果在 IP socket 上监听,则返回操作系统报告的绑定的 address、地址 family 名称、以及服务器 port(用于查找在获取操作系统分配的地址时分配的端口):{ port: 12346, family: 'IPv4', address: '127.0.0.1' }

对于在管道或 Unix 域套接字上监听的 server,该名称将返回为字符串。

const server = net.createServer((socket) => {
  socket.end('再见\n');
}).on('error', (err) => {
  // 处理错误
  throw err;
});

// 获取任意未使用的端口。
server.listen(() => {
  console.log('打开服务器', server.address());
});
1
2
3
4
5
6
7
8
9
10
11

'listening' 事件被触发之前、或在调用 server.close() 之后, server.address() 返回 null

🌙 2.4 server.close([callback])

阻止 server 接受新的连接并保持现有的连接。 该函数是异步的,server 将在所有连接结束后关闭并触发 'close' (opens new window) 事件。 可选的 callback 将在 'close' 事件发生时被调用。 与 'close' 事件不同的是,如果 server 在关闭时未打开,回调函数被调用时会传入一个 Error 对象作为唯一参数。

🌙 3.net.Socket 类

此类是 TCP 套接字或流式 IPC (opens new window) 端点的抽象(在 Windows 上使用命名管道,否则使用 Unix 域套接字)。 它也是一个 EventEmitter (opens new window)

net.Socket 可以由用户创建并且直接地与服务器进行交互。 例如,它由 net.createConnection() (opens new window) 返回,因此用户可以使用它与服务器进行通信。

它也可以由 Node.js 创建,并在收到连接时传给用户。 例如,将它传给 net.Server (opens new window) 上触发的 'connection' (opens new window) 事件的监听器,因此用户可以使用它与客户端进行交互。

🌙 3.1 new net.Socket([options])构造函数

创建一个 socket 对象。 新创建的 socket 可以是 TCP socket 也可以是 IPC (opens new window) 端点流,取决于它连接 connect() (opens new window) 到什么。

🌙 3.2 socket事件

事件名称 描述
close 一旦 socket 完全关闭就发出该事件。参数 had_error 是 boolean 类型,表明 socket 被关闭是否取决于传输错误。
connect 当一个 socket 连接成功建立的时候触发该事件。 查看 net.createConnection() (opens new window)
data 当接收到数据的时触发该事件。data 参数是一个 BufferString。数据编码由 socket.setEncoding() (opens new window) 设置。
drain 当写入缓冲区变为空时触发。可以用来做上传节流。也可以查看:socket.write() 的返回值。
end 当 socket 的另一端发送一个 FIN 包的时候触发,从而结束 socket 的可读端。
error 当错误发生时触发。'close' 事件也会紧接着该事件被触发。
lookup 在找到主机之后创建连接之前触发。
timeout 当 socket 超时的时候触发。该事件只是用来通知 socket 已经闲置。用户必须手动关闭。也可以查看:socket.setTimeout() (opens new window)
ready socket准备好使用时触发,'connect' 后立即触发。

🌙 3.3 socket.address()

返回操作系统报告的 socket 的 address、地址的 family 名称、以及 port{ port: 12346, family: 'IPv4', address: '127.0.0.1' }

🌙 3.4 socket.connect()

在给定的socket上启动一个连接。

该方法是异步的。当连接建立了的时候,'connect' (opens new window) 事件将会被触发。如果连接过程中有问题,'error' (opens new window) 事件将会代替 'connect' (opens new window) 事件被触发,并将错误信息传递给 'error' (opens new window) 监听器。 最后一个参数 connectListener,如果指定了,将会被添加为 'connect' (opens new window) 事件的监听器。

const net = require('net');
net.connect({
  port: 80,
  onread: {
    // 为套接字的每次读取复用 4KiB 的 Buffer。
    buffer: Buffer.alloc(4 * 1024),
    callback: function(nread, buf) {
      // 收到的数据在 `buf` 中可用,从 0 到 'nread`。
      console.log(buf.toString('utf8', 0, nread));
    }
  }
});
1
2
3
4
5
6
7
8
9
10
11
12

🌙 3.5socket.destroy([error])

确保在此 socket 上不再有 I/O 活动。 销毁流并关闭连接。有关更多详细信息,参见 writable.destroy() (opens new window)

🌙 3.6 socket.end([data[, encoding]][, callback])

半关闭 socket。 例如发送一个 FIN 包。 服务端仍可以发送数据。

如果指定了 data,则相当于调用 socket.write(data, encoding) 之后再调用 socket.end() (opens new window)。有关更多详细信息,参见 writable.end() (opens new window)

🌙 3.7 socket.setKeepAlive([enable][, initialDelay])

启用/禁用长连接功能, 并且在第一个长连接探针被发送到一个空闲的 socket 之前可选则配置初始延迟。

initialDelay(毫秒)用来设置接收到最后一个数据包和发送第一个长连接探针之间的延迟。将 initialDelay 设置为 0,则会保持默认值(或之前设置的值)不变。

🌙 3.8 socket.write(data[, encoding][, callback])

在 socket 上发送数据。第二个参数制定了字符串的编码。 默认是 UTF8 编码。

如果全部数据都成功刷新到内核的缓冲则返回 true。如果全部或部分数据在用户内中排队,则返回 false。当缓冲再次空闲的时候将触发 'drain' (opens new window) 事件。

当数据最终都被写出之后,可选的 callback 参数将会被执行(可能不会立即执行)。详见 Writable 流的 write() (opens new window) 方法。

🌙 4.net其他方法

🌙 4.1 net.connect()net.createConnection()

net.connect()net.createConnection()的别名。

一个用于创建 net.Socket (opens new window) 的工厂函数,立即使用 socket.connect() (opens new window) 初始化链接,然后返回启动连接的 net.Socket

当连接建立之后,在返回的 socket 上将触发一个 'connect' (opens new window) 事件。若制定了最后一个参数 connectListener,则它将会被添加到 'connect' (opens new window) 事件作为一个监听器。

可能的参数:

  • net.connect(options[, connectListener])
  • net.connect(path[, connectListener\])用于 IPC (opens new window) 连接
  • net.connect(port[, host\][, connectListener]) 用于 TCP 连接。
const net = require('net');
const client = net.createConnection({ port: 8124 }, () => {
  // 'connect' 监听器
  console.log('已连接到服务器');
  client.write('你好世界!\r\n');
});
client.on('data', (data) => {
  console.log(data.toString());
  client.end();
});
client.on('end', () => {
  console.log('已从服务器断开');
});
1
2
3
4
5
6
7
8
9
10
11
12
13

如果要连接到 /tmp/echo.sock

const client = net.createConnection({ path: '/tmp/echo.sock' });
1

🌙 4.1 net.isIP(input)

测试输入是否是 IP 地址。无效的字符串则返回 0,IPv4 地址则返回 4,IPv6 的地址则返回 6

🌙 4.2 net.isIPv4(input)

如果输入是 IPv4 地址则返回 true,否则返回 false

🌙 4.2 net.isIPv6(input)

如果输入是 IPv6 地址则返回 true,否则返回 false