Skip to content
On this page

Node.js 网络编程

Node.js提供了强大的网络编程能力,包括TCP、UDP、HTTP等协议的支持。本章详细介绍Node.js中的网络编程。

TCP服务器和客户端

创建TCP服务器

javascript
const net = require('net');

// 创建TCP服务器
const server = net.createServer((socket) => {
  console.log('客户端已连接');
  
  // 监听客户端数据
  socket.on('data', (data) => {
    console.log('接收数据:', data.toString());
    
    // 回显数据给客户端
    socket.write(`服务器收到: ${data}`);
  });
  
  // 监听客户端断开连接
  socket.on('end', () => {
    console.log('客户端断开连接');
  });
  
  // 监听错误
  socket.on('error', (err) => {
    console.error('Socket错误:', err);
  });
});

// 监听端口
server.listen(8080, () => {
  console.log('TCP服务器运行在端口8080');
});

// 监听服务器错误
server.on('error', (err) => {
  console.error('服务器错误:', err);
});

TCP客户端

javascript
const net = require('net');

// 创建TCP客户端
const client = net.createConnection({ port: 8080 }, () => {
  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);
});

高级TCP服务器示例

javascript
const net = require('net');

class ChatServer {
  constructor() {
    this.clients = new Map();
    this.server = net.createServer(this.handleConnection.bind(this));
  }
  
  handleConnection(socket) {
    const clientId = Date.now().toString();
    this.clients.set(clientId, socket);
    
    console.log(`客户端 ${clientId} 已连接`);
    
    // 发送欢迎消息
    socket.write(`欢迎! 你的ID是: ${clientId}\n`);
    
    // 广播消息给其他客户端
    socket.on('data', (data) => {
      const message = data.toString().trim();
      console.log(`客户端 ${clientId}: ${message}`);
      
      // 向其他客户端广播消息
      for (const [id, clientSocket] of this.clients) {
        if (id !== clientId) {
          clientSocket.write(`[用户${clientId}]: ${message}\n`);
        }
      }
    });
    
    // 处理客户端断开连接
    socket.on('end', () => {
      this.clients.delete(clientId);
      console.log(`客户端 ${clientId} 已断开`);
      
      // 通知其他客户端
      for (const [id, clientSocket] of this.clients) {
        clientSocket.write(`[系统]: 用户${clientId} 已离开聊天室\n`);
      }
    });
    
    socket.on('error', (err) => {
      console.error(`客户端 ${clientId} 错误:`, err);
      this.clients.delete(clientId);
    });
  }
  
  listen(port) {
    this.server.listen(port, () => {
      console.log(`聊天服务器运行在端口 ${port}`);
    });
  }
}

// 启动聊天服务器
const chatServer = new ChatServer();
chatServer.listen(8080);

UDP编程

UDP服务器

javascript
const dgram = require('dgram');

// 创建UDP服务器
const server = dgram.createSocket('udp4');

server.on('error', (err) => {
  console.error('服务器错误:', err);
  server.close();
});

server.on('message', (msg, rinfo) => {
  console.log(`收到消息: ${msg} 来自 ${rinfo.address}:${rinfo.port}`);
  
  // 发送响应
  const response = `服务器收到: ${msg}`;
  server.send(response, rinfo.port, rinfo.address, (err) => {
    if (err) {
      console.error('发送响应失败:', err);
    }
  });
});

server.on('listening', () => {
  const address = server.address();
  console.log(`UDP服务器运行在 ${address.address}:${address.port}`);
});

server.bind(8080);

UDP客户端

javascript
const dgram = require('dgram');

// 创建UDP客户端
const client = dgram.createSocket('udp4');

// 发送消息到服务器
const message = Buffer.from('Hello, UDP Server!');
client.send(message, 8080, 'localhost', (err) => {
  if (err) {
    console.error('发送消息失败:', err);
    client.close();
    return;
  }
  console.log('消息已发送');
});

// 监听服务器响应
client.on('message', (msg, rinfo) => {
  console.log(`收到响应: ${msg} 来自 ${rinfo.address}:${rinfo.port}`);
  client.close();
});

HTTP编程

基础HTTP服务器

javascript
const http = require('http');
const url = require('url');

// 创建HTTP服务器
const server = http.createServer((req, res) => {
  const parsedUrl = url.parse(req.url, true);
  
  console.log(`${req.method} ${req.url}`);
  
  // 设置响应头
  res.setHeader('Content-Type', 'application/json');
  res.setHeader('Access-Control-Allow-Origin', '*');
  
  if (parsedUrl.pathname === '/' && req.method === 'GET') {
    // 根路径响应
    res.writeHead(200);
    res.end(JSON.stringify({ message: 'Hello, Node.js HTTP Server!' }));
  } else if (parsedUrl.pathname === '/api/users' && req.method === 'GET') {
    // API响应
    const users = [
      { id: 1, name: '张三' },
      { id: 2, name: '李四' }
    ];
    res.writeHead(200);
    res.end(JSON.stringify(users));
  } else {
    // 404响应
    res.writeHead(404);
    res.end(JSON.stringify({ error: 'Not Found' }));
  }
});

server.listen(3000, () => {
  console.log('HTTP服务器运行在端口3000');
});

HTTP客户端

javascript
const http = require('http');

// 发送HTTP请求
const options = {
  hostname: 'localhost',
  port: 3000,
  path: '/api/users',
  method: 'GET',
  headers: {
    'Content-Type': 'application/json'
  }
};

const req = http.request(options, (res) => {
  console.log(`状态码: ${res.statusCode}`);
  console.log(`响应头: ${JSON.stringify(res.headers)}`);
  
  let data = '';
  
  res.on('data', (chunk) => {
    data += chunk;
  });
  
  res.on('end', () => {
    console.log('响应内容:', data);
  });
});

req.on('error', (err) => {
  console.error('请求错误:', err);
});

req.end();

HTTPS编程

HTTPS服务器

javascript
const https = require('https');
const fs = require('fs');

// 读取SSL证书
const options = {
  key: fs.readFileSync('./ssl/private-key.pem'),
  cert: fs.readFileSync('./ssl/certificate.pem')
};

// 创建HTTPS服务器
const httpsServer = https.createServer(options, (req, res) => {
  res.writeHead(200);
  res.end('Hello, HTTPS Server!');
});

httpsServer.listen(443, () => {
  console.log('HTTPS服务器运行在端口443');
});

HTTPS客户端

javascript
const https = require('https');

// 发送HTTPS请求
https.get('https://api.github.com/users/octocat', (res) => {
  let data = '';
  
  res.on('data', (chunk) => {
    data += chunk;
  });
  
  res.on('end', () => {
    const userData = JSON.parse(data);
    console.log('用户信息:', userData.name);
  });
}).on('error', (err) => {
  console.error('HTTPS请求错误:', err);
});

WebSocket编程

Node.js原生不支持WebSocket,但可以通过第三方库如ws来实现:

javascript
// 首先安装: npm install ws
const WebSocket = require('ws');

// 创建WebSocket服务器
const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', (ws, req) => {
  console.log('WebSocket客户端连接:', req.socket.remoteAddress);
  
  // 监听消息
  ws.on('message', (message) => {
    console.log('接收消息:', message.toString());
    
    // 广播消息给所有客户端
    wss.clients.forEach((client) => {
      if (client.readyState === WebSocket.OPEN) {
        client.send(`服务器广播: ${message}`);
      }
    });
  });
  
  // 发送欢迎消息
  ws.send('欢迎连接到WebSocket服务器!');
  
  // 监听关闭
  ws.on('close', () => {
    console.log('客户端断开连接');
  });
  
  // 监听错误
  ws.on('error', (err) => {
    console.error('WebSocket错误:', err);
  });
});

console.log('WebSocket服务器运行在端口8080');

网络工具函数

端口扫描器

javascript
const net = require('net');

function scanPort(host, port, timeout = 1000) {
  return new Promise((resolve) => {
    const socket = new net.Socket();
    
    socket.setTimeout(timeout);
    
    socket.connect(port, host, () => {
      socket.destroy();
      resolve({ port, open: true });
    });
    
    socket.on('timeout', () => {
      socket.destroy();
      resolve({ port, open: false });
    });
    
    socket.on('error', () => {
      socket.destroy();
      resolve({ port, open: false });
    });
  });
}

// 扫描端口范围
async function scanPortRange(host, startPort, endPort) {
  const results = [];
  
  for (let port = startPort; port <= endPort; port++) {
    const result = await scanPort(host, port);
    if (result.open) {
      console.log(`端口 ${port} 开放`);
      results.push(port);
    }
  }
  
  return results;
}

网络请求工具

javascript
const https = require('https');
const http = require('http');
const { URL } = require('url');

function makeRequest(urlString, options = {}) {
  return new Promise((resolve, reject) => {
    const url = new URL(urlString);
    const client = url.protocol === 'https:' ? https : http;
    
    const requestOptions = {
      hostname: url.hostname,
      port: url.port || (url.protocol === 'https:' ? 443 : 80),
      path: url.pathname + url.search,
      method: options.method || 'GET',
      headers: options.headers || {}
    };
    
    const req = client.request(requestOptions, (res) => {
      let data = '';
      
      res.on('data', (chunk) => {
        data += chunk;
      });
      
      res.on('end', () => {
        resolve({
          statusCode: res.statusCode,
          headers: res.headers,
          data: data
        });
      });
    });
    
    req.on('error', reject);
    
    if (options.body) {
      req.write(options.body);
    }
    
    req.end();
  });
}

// 使用示例
makeRequest('https://jsonplaceholder.typicode.com/posts/1')
  .then(response => {
    console.log('响应状态:', response.statusCode);
    console.log('响应数据:', response.data);
  })
  .catch(err => {
    console.error('请求失败:', err);
  });

网络安全考虑

防止慢速攻击

javascript
const http = require('http');

const server = http.createServer((req, res) => {
  // 设置请求和响应超时
  req.setTimeout(30000, () => {
    console.log('请求超时');
    res.destroy();
  });
  
  res.setTimeout(30000, () => {
    console.log('响应超时');
    res.destroy();
  });
  
  // 处理请求
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello World');
});

server.listen(3000);

请求限制

javascript
const http = require('http');
const clientConnections = new Map();

const server = http.createServer((req, res) => {
  const clientIP = req.socket.remoteAddress;
  
  // 限制每个IP的连接数
  const connections = clientConnections.get(clientIP) || 0;
  if (connections > 10) {
    res.writeHead(429, { 'Content-Type': 'text/plain' });
    res.end('Too many requests');
    return;
  }
  
  // 增加连接计数
  clientConnections.set(clientIP, connections + 1);
  
  req.on('close', () => {
    // 减少连接计数
    const currentConnections = clientConnections.get(clientIP);
    if (currentConnections > 1) {
      clientConnections.set(clientIP, currentConnections - 1);
    } else {
      clientConnections.delete(clientIP);
    }
  });
  
  // 处理请求
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello World');
});

server.listen(3000);

Node.js的网络编程能力使其成为构建高性能网络应用的理想选择。通过合理使用TCP、UDP、HTTP等协议,可以构建各种类型的网络服务和应用。