MST
星途 面试题库

面试题:Node.js Socket如何实现可靠的数据传输

在Node.js的Socket编程中,网络环境复杂多变,可能存在丢包、延迟等问题。描述如何通过代码实现可靠的数据传输,比如使用哪些机制(如确认机制、重传机制等)来保证数据准确无误且有序地到达接收方。详细说明实现思路及关键代码片段。
27.2万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 确认机制:发送方发送数据后,等待接收方返回确认消息(ACK)。若在规定时间内收到ACK,表明数据成功接收;否则,认为数据丢失。
  2. 重传机制:若发送方在超时时间内未收到ACK,重新发送数据。可设置最大重传次数,避免无限重传。
  3. 序列号:为每个发送的数据段添加序列号,接收方根据序列号对数据进行排序,确保数据按顺序处理。

关键代码片段

  1. 发送方代码
const net = require('net');
const socket = new net.Socket();
const serverAddress = '127.0.0.1';
const serverPort = 8080;
const maxRetries = 3;
const timeout = 1000; // 1秒超时

let sequenceNumber = 0;
let retries = 0;
let timer;

function sendData(data) {
    const packet = {
        seq: sequenceNumber++,
        data: data
    };
    socket.write(JSON.stringify(packet));
    startRetransmissionTimer();
}

function startRetransmissionTimer() {
    timer = setTimeout(() => {
        if (retries < maxRetries) {
            console.log('未收到ACK,重传数据');
            sendData(currentData);
            retries++;
        } else {
            console.log('达到最大重传次数,放弃重传');
        }
    }, timeout);
}

function clearRetransmissionTimer() {
    clearTimeout(timer);
    retries = 0;
}

socket.connect(serverPort, serverAddress, () => {
    const currentData = 'Hello, Server!';
    sendData(currentData);
});

socket.on('data', (data) => {
    const response = JSON.parse(data.toString());
    if (response.type === 'ACK' && response.seq === sequenceNumber - 1) {
        console.log('收到ACK,数据传输成功');
        clearRetransmissionTimer();
    }
});

socket.on('error', (err) => {
    console.error('Socket error:', err);
});

socket.on('close', () => {
    console.log('Socket closed');
});
  1. 接收方代码
const net = require('net');
const server = net.createServer((socket) => {
    const receivedPackets = [];

    socket.on('data', (data) => {
        const packet = JSON.parse(data.toString());
        receivedPackets.push(packet);
        receivedPackets.sort((a, b) => a.seq - b.seq);

        // 处理按序到达的数据
        let expectedSeq = 0;
        while (receivedPackets.length > 0 && receivedPackets[0].seq === expectedSeq) {
            const processedPacket = receivedPackets.shift();
            console.log('处理数据:', processedPacket.data);
            expectedSeq++;
        }

        // 发送ACK
        const ack = {
            type: 'ACK',
            seq: packet.seq
        };
        socket.write(JSON.stringify(ack));
    });

    socket.on('error', (err) => {
        console.error('Socket error:', err);
    });

    socket.on('close', () => {
        console.log('Socket closed');
    });
});

const port = 8080;
server.listen(port, () => {
    console.log(`Server listening on port ${port}`);
});