Node.js中net模块详解

发布于:2025-04-16 ⋅ 阅读:(37) ⋅ 点赞:(0)

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 模块的主要特点:

  1. 提供 TCP 服务器和客户端功能
  2. 支持 IPv4 和 IPv6
  3. 支持 Unix 域套接字
  4. 提供事件驱动 API
  5. 支持流式处理

使用建议:

  1. 使用事件处理连接和数据
  2. 正确处理错误情况
  3. 设置适当的超时和保活
  4. 使用无延迟模式提高性能
  5. 考虑使用更高级的框架(如 Socket.io)简化开发

网站公告

今日签到

点亮在社区的每一天
去签到