Node.js 中 net 模块 API 详解
Node.js 的 net 模块提供了基于 TCP/IP 的网络功能,用于创建 TCP 服务器和客户端。以下是 net 模块的所有 API 详解:
1. 创建 TCP 服务器
const net = require('net');
// 1. 基本服务器
const server = net.createServer((socket) => {
console.log('客户端已连接');
socket.on('data', (data) => {
console.log('收到数据:', data.toString());
socket.write('服务器已收到数据');
});
socket.on('end', () => {
console.log('客户端已断开连接');
});
socket.on('error', (err) => {
console.error('Socket 错误:', err);
});
});
server.listen(3000, '127.0.0.1', () => {
console.log('服务器运行在 127.0.0.1:3000');
});
// 2. 使用 Server 类
const server2 = new net.Server((socket) => {
console.log('客户端已连接');
});
server2.listen(3001);
// 3. 处理连接事件
server.on('connection', (socket) => {
console.log('新连接建立');
// 设置超时
socket.setTimeout(60000); // 60 秒
// 设置保活
socket.setKeepAlive(true, 60000);
// 设置缓冲区大小
socket.setNoDelay(true);
});
// 4. 错误处理
server.on('error', (err) => {
console.error('服务器错误:', err);
});
// 5. 关闭服务器
server.close(() => {
console.log('服务器已关闭');
});
2. 服务器方法
// 1. 启动服务器
server.listen(3000, '127.0.0.1', () => {
console.log('服务器运行在 127.0.0.1:3000');
});
// 2. 关闭服务器
server.close(() => {
console.log('服务器已关闭');
});
// 3. 获取服务器地址信息
const address = server.address();
console.log('服务器地址:', address);
// { address: '127.0.0.1', family: 'IPv4', port: 3000 }
// 4. 获取最大连接数
const maxConnections = server.maxConnections;
console.log('最大连接数:', maxConnections);
// 5. 设置最大连接数
server.maxConnections = 100;
// 6. 获取当前连接数
const connections = server.connections;
console.log('当前连接数:', connections);
3. Socket 对象
// 1. Socket 属性
server.on('connection', (socket) => {
console.log('远程地址:', socket.remoteAddress);
console.log('远程端口:', socket.remotePort);
console.log('本地地址:', socket.localAddress);
console.log('本地端口:', socket.localPort);
console.log('字节读取:', socket.bytesRead);
console.log('字节写入:', socket.bytesWritten);
console.log('超时设置:', socket.timeout);
console.log('保活设置:', socket.keepAlive);
console.log('保活初始延迟:', socket.keepAliveInitialDelay);
console.log('无延迟设置:', socket.noDelay);
console.log('可写状态:', socket.writable);
console.log('可读状态:', socket.readable);
console.log('已销毁:', socket.destroyed);
});
// 2. Socket 事件
server.on('connection', (socket) => {
// 数据事件
socket.on('data', (data) => {
console.log('收到数据:', data.toString());
});
// 结束事件
socket.on('end', () => {
console.log('连接结束');
});
// 关闭事件
socket.on('close', (hadError) => {
console.log('连接关闭, 是否有错误:', hadError);
});
// 错误事件
socket.on('error', (err) => {
console.error('Socket 错误:', err);
});
// 超时事件
socket.on('timeout', () => {
console.log('连接超时');
});
// 可写事件
socket.on('drain', () => {
console.log('缓冲区已清空');
});
// 查找事件
socket.on('lookup', (err, address, family, host) => {
console.log('DNS 查找结果:', address, family, host);
});
// 准备事件
socket.on('ready', () => {
console.log('Socket 已准备就绪');
});
});
// 3. Socket 方法
server.on('connection', (socket) => {
// 写入数据
socket.write('Hello Client\n');
// 结束写入
socket.end();
// 暂停读取
socket.pause();
// 恢复读取
socket.resume();
// 设置超时
socket.setTimeout(60000);
// 设置保活
socket.setKeepAlive(true, 60000);
// 设置无延迟
socket.setNoDelay(true);
// 获取地址信息
const address = socket.address();
console.log('Socket 地址:', address);
// 销毁 Socket
socket.destroy();
});
4. 创建 TCP 客户端
// 1. 基本客户端
const client = new net.Socket();
client.connect(3000, '127.0.0.1', () => {
console.log('已连接到服务器');
client.write('Hello Server');
});
client.on('data', (data) => {
console.log('收到数据:', data.toString());
});
client.on('end', () => {
console.log('与服务器断开连接');
});
client.on('error', (err) => {
console.error('客户端错误:', err);
});
// 2. 使用 createConnection
const client2 = net.createConnection(3000, '127.0.0.1', () => {
console.log('已连接到服务器');
client2.write('Hello Server');
});
// 3. 使用 Unix 域套接字
const unixClient = net.createConnection('/tmp/socket.sock', () => {
console.log('已连接到 Unix 域套接字');
});
// 4. 使用选项对象
const client3 = net.createConnection({
port: 3000,
host: '127.0.0.1',
timeout: 5000,
keepAlive: true,
keepAliveInitialDelay: 10000,
noDelay: true
}, () => {
console.log('已连接到服务器');
});
5. 客户端事件
// 1. 连接事件
client.on('connect', () => {
console.log('已连接到服务器');
});
// 2. 数据事件
client.on('data', (data) => {
console.log('收到数据:', data.toString());
});
// 3. 结束事件
client.on('end', () => {
console.log('与服务器断开连接');
});
// 4. 关闭事件
client.on('close', (hadError) => {
console.log('连接关闭, 是否有错误:', hadError);
});
// 5. 错误事件
client.on('error', (err) => {
console.error('客户端错误:', err);
});
// 6. 超时事件
client.on('timeout', () => {
console.log('连接超时');
});
// 7. 可写事件
client.on('drain', () => {
console.log('缓冲区已清空');
});
// 8. 查找事件
client.on('lookup', (err, address, family, host) => {
console.log('DNS 查找结果:', address, family, host);
});
// 9. 准备事件
client.on('ready', () => {
console.log('Socket 已准备就绪');
});
6. 客户端方法
// 1. 连接到服务器
client.connect(3000, '127.0.0.1', () => {
console.log('已连接到服务器');
});
// 2. 写入数据
client.write('Hello Server\n');
// 3. 结束连接
client.end();
// 4. 销毁连接
client.destroy();
// 5. 暂停读取
client.pause();
// 6. 恢复读取
client.resume();
// 7. 设置超时
client.setTimeout(5000);
// 8. 设置保活
client.setKeepAlive(true, 10000);
// 9. 设置无延迟
client.setNoDelay(true);
// 10. 获取地址信息
const address = client.address();
console.log('客户端地址:', address);
7. 网络工具函数
// 1. 检查是否为 IP 地址
const isIP = net.isIP('192.168.1.1');
console.log('是否为 IP 地址:', isIP); // 4 (IPv4) 或 6 (IPv6) 或 0 (不是 IP)
// 2. 检查是否为 IPv4 地址
const isIPv4 = net.isIPv4('192.168.1.1');
console.log('是否为 IPv4 地址:', isIPv4); // true 或 false
// 3. 检查是否为 IPv6 地址
const isIPv6 = net.isIPv6('2001:db8::1');
console.log('是否为 IPv6 地址:', isIPv6); // true 或 false
// 4. 获取本地 IP 地址
const os = require('os');
const interfaces = os.networkInterfaces();
console.log('网络接口:', interfaces);
8. 实际应用示例
// 1. 回显服务器
const echoServer = net.createServer((socket) => {
console.log('客户端已连接');
socket.on('data', (data) => {
console.log('收到数据:', data.toString());
socket.write(data); // 回显数据
});
socket.on('end', () => {
console.log('客户端已断开连接');
});
});
echoServer.listen(3000, '127.0.0.1');
// 2. 聊天服务器
const chatServer = net.createServer();
const clients = [];
chatServer.on('connection', (socket) => {
console.log('新客户端连接');
clients.push(socket);
socket.write('欢迎加入聊天室!\n');
socket.on('data', (data) => {
const message = data.toString().trim();
console.log('收到消息:', message);
// 广播消息给所有客户端
clients.forEach(client => {
if (client !== socket) {
client.write(`客户端 ${socket.remotePort} 说: ${message}\n`);
}
});
});
socket.on('end', () => {
console.log('客户端断开连接');
const index = clients.indexOf(socket);
if (index !== -1) {
clients.splice(index, 1);
}
});
});
chatServer.listen(3001, '127.0.0.1');
// 3. 端口扫描器
function scanPort(host, port) {
return new Promise((resolve) => {
const socket = new net.Socket();
socket.setTimeout(1000);
socket.on('connect', () => {
console.log(`端口 ${port} 开放`);
socket.destroy();
resolve(true);
});
socket.on('timeout', () => {
socket.destroy();
resolve(false);
});
socket.on('error', () => {
socket.destroy();
resolve(false);
});
socket.connect(port, host);
});
}
async function scanPorts(host, startPort, endPort) {
console.log(`开始扫描主机 ${host} 的端口 ${startPort}-${endPort}`);
for (let port = startPort; port <= endPort; port++) {
const isOpen = await scanPort(host, port);
if (isOpen) {
console.log(`端口 ${port} 开放`);
}
}
console.log('扫描完成');
}
// scanPorts('127.0.0.1', 1, 1024);
9. 高级功能
// 1. 多路复用服务器
const multiplexServer = net.createServer();
const channels = {};
multiplexServer.on('connection', (socket) => {
console.log('新连接建立');
socket.on('data', (data) => {
const message = JSON.parse(data.toString());
if (message.type === 'register') {
// 注册通道
channels[message.channel] = socket;
socket.channel = message.channel;
socket.write(JSON.stringify({ type: 'registered', channel: message.channel }) + '\n');
} else if (message.type === 'message') {
// 转发消息
const targetChannel = channels[message.target];
if (targetChannel) {
targetChannel.write(JSON.stringify({
type: 'message',
from: socket.channel,
data: message.data
}) + '\n');
}
}
});
socket.on('end', () => {
if (socket.channel) {
delete channels[socket.channel];
}
});
});
multiplexServer.listen(3002, '127.0.0.1');
// 2. 负载均衡器
const backendServers = [
{ host: '127.0.0.1', port: 3003 },
{ host: '127.0.0.1', port: 3004 },
{ host: '127.0.0.1', port: 3005 }
];
let currentServer = 0;
const loadBalancer = net.createServer((clientSocket) => {
const server = backendServers[currentServer];
currentServer = (currentServer + 1) % backendServers.length;
console.log(`将客户端连接到后端服务器 ${server.host}:${server.port}`);
const serverSocket = net.createConnection(server.port, server.host, () => {
clientSocket.write('已连接到后端服务器\n');
});
clientSocket.pipe(serverSocket);
serverSocket.pipe(clientSocket);
clientSocket.on('error', (err) => {
console.error('客户端错误:', err);
});
serverSocket.on('error', (err) => {
console.error('服务器错误:', err);
});
clientSocket.on('end', () => {
serverSocket.end();
});
serverSocket.on('end', () => {
clientSocket.end();
});
});
loadBalancer.listen(3000, '127.0.0.1');
10. 性能优化
// 1. 使用连接池
class ConnectionPool {
constructor(host, port, size) {
this.host = host;
this.port = port;
this.size = size;
this.pool = [];
this.available = [];
}
async initialize() {
for (let i = 0; i < this.size; i++) {
const socket = await this.createConnection();
this.pool.push(socket);
this.available.push(socket);
}
}
createConnection() {
return new Promise((resolve, reject) => {
const socket = new net.Socket();
socket.connect(this.port, this.host, () => {
resolve(socket);
});
socket.on('error', (err) => {
reject(err);
});
});
}
acquire() {
if (this.available.length === 0) {
return null;
}
return this.available.pop();
}
release(socket) {
if (this.pool.includes(socket)) {
this.available.push(socket);
}
}
}
// 2. 使用缓冲区
const bufferServer = net.createServer((socket) => {
let buffer = Buffer.alloc(0);
socket.on('data', (chunk) => {
buffer = Buffer.concat([buffer, chunk]);
// 处理完整消息
while (buffer.length >= 4) {
const messageLength = buffer.readUInt32BE(0);
if (buffer.length >= messageLength + 4) {
const message = buffer.slice(4, messageLength + 4);
buffer = buffer.slice(messageLength + 4);
// 处理消息
console.log('收到消息:', message.toString());
socket.write(Buffer.concat([
Buffer.from([0, 0, 0, 4]), // 4 字节长度
Buffer.from('OK\n')
]));
} else {
break;
}
}
});
});
bufferServer.listen(3006, '127.0.0.1');
net 模块的主要特点:
- 提供 TCP 服务器和客户端功能
- 支持 IPv4 和 IPv6
- 支持 Unix 域套接字
- 提供事件驱动 API
- 支持流式处理
使用建议:
- 使用事件处理连接和数据
- 正确处理错误情况
- 设置适当的超时和保活
- 使用无延迟模式提高性能
- 考虑使用更高级的框架(如 Socket.io)简化开发