MST

星途 面试题库

面试题:Node.js TCP 通信的安全机制与可靠性保障

在 Node.js 实现的 TCP 客户端与服务端通信系统中,如何保障通信的安全性和可靠性?请详细说明如何实现数据加密(如采用 SSL/TLS 协议)、防止数据丢失和篡改、处理网络异常中断并进行重连等措施,同时给出在实际项目中相关配置和代码实现思路。
29.0万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试

1. 数据加密(采用 SSL/TLS 协议)

  • 实现思路:在 Node.js 中,tls 模块提供了对 SSL/TLS 协议的支持。服务端和客户端都需要配置相应的证书和密钥。
  • 服务端配置与代码实现
const tls = require('tls');
const fs = require('fs');

const options = {
  key: fs.readFileSync('server-key.pem'),
  cert: fs.readFileSync('server-cert.pem'),
  // 如果需要双向认证(客户端也提供证书)
  requestCert: true,
  rejectUnauthorized: true
};

const server = tls.createServer(options, (socket) => {
  socket.write('Welcome!\n');
  socket.setEncoding('utf8');
  socket.on('data', (data) => {
    console.log('Received: %s', data);
  });
  socket.on('end', () => {
    console.log('Connection closed');
  });
});

server.listen(8000, () => {
  console.log('Server listening on port 8000');
});
  • 客户端配置与代码实现
const tls = require('tls');
const fs = require('fs');

const options = {
  key: fs.readFileSync('client-key.pem'),
  cert: fs.readFileSync('client-cert.pem'),
  ca: [fs.readFileSync('ca-cert.pem')]
};

const socket = tls.connect(8000, 'localhost', options, () => {
  console.log('Connected to server');
  socket.write('Hello, server!\n');
});

socket.setEncoding('utf8');
socket.on('data', (data) => {
  console.log('Received: %s', data);
});

socket.on('end', () => {
  console.log('Connection closed');
});

2. 防止数据丢失和篡改

  • 数据校验
    • 实现思路:在发送端计算数据的哈希值(如使用 crypto 模块的 createHash 方法),并将哈希值与数据一同发送。接收端接收到数据后,重新计算哈希值并与接收到的哈希值进行比对。
    • 代码示例
const crypto = require('crypto');

// 发送端
function sendDataWithHash(data, socket) {
  const hash = crypto.createHash('sha256').update(data).digest('hex');
  const message = `${data}:${hash}`;
  socket.write(message);
}

// 接收端
function verifyData(data) {
  const parts = data.split(':');
  const originalData = parts[0];
  const receivedHash = parts[1];
  const calculatedHash = crypto.createHash('sha256').update(originalData).digest('hex');
  return calculatedHash === receivedHash;
}
  • 序列号
    • 实现思路:为每个发送的数据包分配一个唯一的序列号。接收端根据序列号检查数据包是否按顺序接收,若有缺失可要求发送端重发。
    • 代码示例
let sequenceNumber = 0;
function sendDataWithSequence(data, socket) {
  const message = `${sequenceNumber++}:${data}`;
  socket.write(message);
}

function handleReceivedData(data) {
  const parts = data.split(':', 2);
  const receivedSequence = parseInt(parts[0]);
  const receivedData = parts[1];
  // 此处可根据 receivedSequence 进行顺序检查和处理
}

3. 处理网络异常中断并进行重连

  • 实现思路:使用 socketerrorclose 事件来检测网络异常。在发生异常时,启动一个重连机制,设置一定的重试间隔。
  • 代码实现
const net = require('net');

let reconnectInterval = 1000; // 初始重连间隔 1 秒
function connectToServer() {
  const socket = net.connect(8000, 'localhost', () => {
    console.log('Connected to server');
    socket.write('Hello, server!\n');
    reconnectInterval = 1000; // 连接成功,重置重连间隔
  });

  socket.on('error', (err) => {
    console.error('Connection error:', err.message);
    setTimeout(() => {
      connectToServer();
      reconnectInterval = Math.min(reconnectInterval * 2, 10000); // 指数退避,最长重连间隔 10 秒
    }, reconnectInterval);
  });

  socket.on('close', () => {
    console.log('Connection closed. Reconnecting...');
    setTimeout(() => {
      connectToServer();
      reconnectInterval = Math.min(reconnectInterval * 2, 10000);
    }, reconnectInterval);
  });
}

connectToServer();