In this lesson, you will learn how to reconstruct incomplete data frames received over fragmented TCP streams by using persistent buffers to track incoming binary fragments.
The TCP Fragmentation Problem
When you communicate over TCP, the network does not guarantee that one write call from a sender results in one data event on your receiver. Because TCP is a streaming protocol, a single logical message (a "frame") might arrive in several chunks, or multiple frames might be mashed together into one buffer. If you try to parse a protocol header before you have received the entire frame, your application will crash or process corrupt data.
Persistent Buffers as Staging Areas
To solve this, you need a "stray" or "persistent" buffer that lives outside the scope of individual data events. Think of this as a workbench where you accumulate fragments until you have enough pieces to form a complete message.
Here is how you manage this state:
- Initialize: Create a buffer or an array to store bytes that haven't been processed yet.
- Concatenate: Every time a
dataevent fires, append the new chunk to your persistent storage. - Parse and Slice: Check if your storage contains at least one full frame. If it does, slice that frame off, process it, and keep the remaining data in your storage for the next event.
let buffer = Buffer.alloc(0);
socket.on('data', (chunk) => {
// Concatenate new fragment with existing leftovers
buffer = Buffer.concat([buffer, chunk]);
// Process as many full frames as possible
while (buffer.length >= FRAME_SIZE) {
const frame = buffer.subarray(0, FRAME_SIZE);
processFrame(frame);
// Update buffer to hold only the remaining incomplete data
buffer = Buffer.subarray(FRAME_SIZE);
}
});
By using buffer.subarray() (which provides a view into the original memory), you keep the remaining, incomplete data ready for the next arrival of bytes. This loop ensures that even if a frame is split across three different network packets, your logic will wait patiently until the final byte arrives before attempting to parse the payload.
Key Takeaway: Always maintain a persistent buffer to accumulate incoming TCP chunks, and only parse data once the cumulative length satisfies your protocol's frame requirements.