MST

星途 面试题库

面试题:JavaScript 实现 Node 非 HTTP 网络通信时如何处理连接稳定性

在使用 JavaScript 进行 Node 非 HTTP 网络通信编程时,网络连接可能会出现不稳定的情况,例如丢包、延迟等。请描述你会采取哪些策略和技术手段来检测连接是否稳定,以及在连接不稳定时如何进行重连、数据缓存与补发等操作以保障通信的可靠性。
40.8万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

检测连接是否稳定

  1. 心跳机制

    • 定期(例如每隔一定时间间隔,如1 - 5秒)向对方发送一个简单的心跳包(可以是一个特定格式的消息,如{type: 'heartbeat'})。
    • 在接收端,当收到心跳包时,回复一个确认消息(如{type: 'heartbeat - ack'})。
    • 如果发送端在一定时间内(如心跳间隔的2 - 3倍时间)没有收到确认消息,则认为连接可能不稳定。
  2. 监测数据传输时间

    • 在发送数据时记录发送时间戳,在接收端收到数据后,将数据连同接收时间戳一起返回。
    • 发送端收到返回数据后,计算数据往返时间(RTT)。如果RTT超过某个设定的阈值(例如根据历史数据或经验设定为100ms - 1s),则可能表示连接不稳定。
  3. 检测丢包

    • 为每个发送的数据包添加一个序列号。
    • 接收端按照序列号顺序接收数据,如果检测到序列号不连续,且缺失的序列号在一定范围内(例如连续缺失3个以内),则认为可能发生了丢包,通知发送端。

连接不稳定时的重连操作

  1. 立即重连
    • 当检测到连接不稳定(如心跳超时、RTT超阈值或确认丢包)时,立即尝试重新建立连接。使用net模块(假设是TCP连接)的createConnection方法(对于UDP连接,可以重新初始化dgram套接字)。
    • 例如,对于TCP连接:
const net = require('net');
const client = new net.Socket();
function reconnect() {
    client.connect({port: 8080, host: '127.0.0.1'}, () => {
        console.log('Re - connected');
    });
    client.on('error', (err) => {
        console.error('Re - connect error:', err);
        setTimeout(reconnect, 1000);
    });
}
  1. 指数退避重连
    • 每次重连失败后,增加重连的时间间隔。例如,第一次重连间隔1秒,第二次2秒,第三次4秒,以此类推。
    • 代码示例:
const net = require('net');
const client = new net.Socket();
let reconnectInterval = 1000;
function reconnect() {
    client.connect({port: 8080, host: '127.0.0.1'}, () => {
        console.log('Re - connected');
        reconnectInterval = 1000;
    });
    client.on('error', (err) => {
        console.error('Re - connect error:', err);
        setTimeout(reconnect, reconnectInterval);
        reconnectInterval *= 2;
    });
}

数据缓存与补发

  1. 数据缓存
    • 使用一个数组或队列来缓存需要发送的数据。例如,对于需要发送的数据data
const dataQueue = [];
function sendData(data) {
    dataQueue.push(data);
    if (!client.writable) {
        return;
    }
    sendQueuedData();
}
  1. 补发
    • 当连接重新建立成功后,遍历缓存的数据队列,依次重新发送数据。
    • 例如:
function sendQueuedData() {
    while (dataQueue.length > 0 && client.writable) {
        const data = dataQueue.shift();
        client.write(data);
    }
}
client.on('connect', () => {
    sendQueuedData();
});