TCP/UDP编程
TCP编程基础
TCP(传输控制协议)是面向连接的可靠传输协议,Node.js通过net
模块提供TCP编程能力。创建TCP服务器只需几行代码:
const net = require('net');
const server = net.createServer((socket) => {
console.log('客户端已连接');
socket.on('data', (data) => {
console.log(`收到数据: ${data}`);
socket.write(`ECHO: ${data}`);
});
socket.on('end', () => {
console.log('客户端断开连接');
});
});
server.listen(8124, () => {
console.log('服务器启动在8124端口');
});
TCP客户端实现同样简单:
const net = require('net');
const client = net.connect({port: 8124}, () => {
console.log('连接到服务器');
client.write('Hello TCP!');
});
client.on('data', (data) => {
console.log(data.toString());
client.end();
});
client.on('end', () => {
console.log('断开服务器连接');
});
TCP粘包处理
TCP是流式协议,需要处理消息边界问题。常见解决方案:
- 固定长度协议:
// 发送方
const data = Buffer.alloc(4);
data.writeInt32BE(1234, 0);
socket.write(data);
// 接收方
let buffer = Buffer.alloc(0);
socket.on('data', (chunk) => {
buffer = Buffer.concat([buffer, chunk]);
while(buffer.length >= 4) {
const value = buffer.readInt32BE(0);
console.log(value);
buffer = buffer.slice(4);
}
});
- 分隔符协议:
// 发送方
socket.write('消息内容|');
// 接收方
let buffer = '';
socket.on('data', (chunk) => {
buffer += chunk.toString();
const messages = buffer.split('|');
buffer = messages.pop();
messages.forEach(msg => console.log(msg));
});
UDP编程实现
UDP通过dgram
模块实现,适合实时性要求高的场景:
const dgram = require('dgram');
const server = dgram.createSocket('udp4');
server.on('message', (msg, rinfo) => {
console.log(`服务器收到: ${msg} 来自 ${rinfo.address}:${rinfo.port}`);
});
server.bind(41234, () => {
console.log('UDP服务器启动');
});
const client = dgram.createSocket('udp4');
client.send('Hello UDP', 41234, 'localhost', (err) => {
if (err) throw err;
client.close();
});
协议选择考量
TCP适用场景:
- 需要可靠传输(如文件传输)
- 需要保证数据顺序
- 长连接通信(如实时聊天)
UDP适用场景:
- 实时性要求高(如视频会议)
- 允许少量丢包(如DNS查询)
- 广播/多播应用
高级应用示例
TCP代理服务器实现:
const net = require('net');
const proxy = net.createServer((clientSocket) => {
const serverSocket = net.connect(80, 'example.com');
clientSocket.pipe(serverSocket);
serverSocket.pipe(clientSocket);
serverSocket.on('error', (err) => {
console.error('服务器连接错误:', err);
clientSocket.end();
});
});
proxy.listen(8080);
UDP组播示例:
const dgram = require('dgram');
const socket = dgram.createSocket('udp4');
socket.on('listening', () => {
socket.addMembership('224.0.0.114');
});
socket.on('message', (msg, rinfo) => {
console.log(`收到组播消息: ${msg}`);
});
socket.bind(41234);
// 发送组播
const client = dgram.createSocket('udp4');
client.send('组播测试', 41234, '224.0.0.114');
性能优化技巧
- TCP连接池管理:
class ConnectionPool {
constructor(maxConnections = 10) {
this.pool = [];
this.max = maxConnections;
}
getConnection() {
if(this.pool.length > 0) {
return Promise.resolve(this.pool.pop());
}
return new Promise((resolve) => {
const conn = net.createConnection(8124);
conn.on('connect', () => resolve(conn));
});
}
releaseConnection(conn) {
if(this.pool.length < this.max) {
this.pool.push(conn);
} else {
conn.end();
}
}
}
- UDP批量发送优化:
function batchSend(socket, messages, port, address) {
let index = 0;
function sendNext() {
if(index >= messages.length) return;
socket.send(messages[index], port, address, (err) => {
if(err) console.error('发送失败:', err);
index++;
setImmediate(sendNext); // 避免堆栈溢出
});
}
sendNext();
}
错误处理实践
TCP错误处理最佳实践:
server.on('error', (err) => {
if(err.code === 'EADDRINUSE') {
console.error('端口被占用,正在重试...');
setTimeout(() => {
server.close();
server.listen(PORT);
}, 1000);
} else {
console.error('服务器错误:', err);
}
});
socket.on('error', (err) => {
console.error('连接错误:', err);
// 根据错误类型决定是否重连
});
UDP错误处理模式:
udpSocket.on('error', (err) => {
console.error(`UDP错误: ${err.stack}`);
udpSocket.close();
// 对于关键服务应该尝试重启
if(isCritical) {
setTimeout(createUDPServer, 1000);
}
});
实际应用案例
实现简单的RPC框架:
// TCP-RPC服务器
class RPCServer {
constructor(port) {
this.methods = {};
this.server = net.createServer(this.handleConnection.bind(this));
this.server.listen(port);
}
register(name, method) {
this.methods[name] = method;
}
handleConnection(socket) {
let buffer = '';
socket.on('data', (data) => {
buffer += data;
const requests = buffer.split('\n');
buffer = requests.pop();
requests.forEach(request => {
try {
const {id, method, params} = JSON.parse(request);
const result = this.methods[method](...params);
socket.write(JSON.stringify({id, result}) + '\n');
} catch(err) {
socket.write(JSON.stringify({error: err.message}) + '\n');
}
});
});
}
}
// 使用示例
const rpc = new RPCServer(8080);
rpc.register('add', (a, b) => a + b);
UDP实现服务发现:
// 服务提供方
const beacon = dgram.createSocket('udp4');
setInterval(() => {
const serviceInfo = JSON.stringify({
name: 'my-service',
port: 3000,
timestamp: Date.now()
});
beacon.send(serviceInfo, 8888, '255.255.255.255');
}, 5000);
// 服务发现方
const discover = dgram.createSocket('udp4');
discover.bind(8888, () => {
discover.setBroadcast(true);
});
const services = {};
discover.on('message', (msg) => {
const info = JSON.parse(msg);
services[info.name] = {
...info,
lastSeen: Date.now()
};
});
// 清理过期服务
setInterval(() => {
const now = Date.now();
Object.keys(services).forEach(name => {
if(now - services[name].lastSeen > 10000) {
delete services[name];
}
});
}, 5000);
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:HTTPS与安全通信
下一篇:WebSocket实现