Appearance
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等协议,可以构建各种类型的网络服务和应用。