面试题答案
一键面试保证数据包按序重组的实现机制
- 标识符:
- 序列号(Sequence Number):在发送端为每个分片数据包分配一个唯一的序列号,通常从 0 开始,按顺序递增。接收端可以根据这个序列号来确定数据包的顺序。
- 算法:
- 缓存与排序算法:接收端接收到分片数据包后,先将其放入一个缓存队列中。根据序列号对缓存中的数据包进行排序,然后按照顺序依次取出重组。例如,可以使用 JavaScript 的数组作为缓存队列,利用数组的
sort
方法根据序列号进行排序。
- 缓存与排序算法:接收端接收到分片数据包后,先将其放入一个缓存队列中。根据序列号对缓存中的数据包进行排序,然后按照顺序依次取出重组。例如,可以使用 JavaScript 的数组作为缓存队列,利用数组的
代码框架
const net = require('net');
// 接收端
const server = net.createServer((socket) => {
const packetBuffer = [];
socket.on('data', (data) => {
// 假设数据格式为:序列号(4 字节)+ 数据内容
const sequenceNumber = data.readUInt32BE(0);
const packetData = data.slice(4);
packetBuffer.push({ sequenceNumber, packetData });
packetBuffer.sort((a, b) => a.sequenceNumber - b.sequenceNumber);
// 尝试重组数据包
let completePacket = '';
while (packetBuffer.length > 0 && packetBuffer[0].sequenceNumber === completePacket.length / 4) {
completePacket += packetBuffer.shift().packetData.toString('utf8');
}
if (completePacket) {
console.log('重组后的完整数据包:', completePacket);
}
});
socket.on('end', () => {
console.log('连接已关闭');
});
});
server.listen(8080, () => {
console.log('服务器已启动,监听端口 8080');
});
// 发送端
const client = new net.Socket();
client.connect(8080, '127.0.0.1', () => {
const message = 'Hello, TCP Packet Fragmentation!';
const maxFragmentSize = 10;
for (let i = 0; i < message.length; i += maxFragmentSize) {
const fragment = message.slice(i, i + maxFragmentSize);
const buffer = Buffer.alloc(4 + fragment.length);
buffer.writeUInt32BE(i / maxFragmentSize, 0);
buffer.write(fragment, 4);
client.write(buffer);
}
client.end();
});
在上述代码中:
- 发送端为每个分片数据包添加了序列号,然后发送给接收端。
- 接收端在接收到数据后,根据序列号进行排序并尝试重组数据包。当接收到的数据包序列号连续时,将其内容拼接成完整的数据包。