SubnetLayer

Basic Data Transfer

From an application's write() to segments on the wire

Step 1 of 2 — understand the idea. Read this first and the packet trace will confirm what you already expect, instead of teaching you two things at once.

What you'll be able to do

Your program calls write() with some bytes and expects them to appear, in order and intact, at the other end. Underneath, the network can only carry small, independent packets that may be lost, duplicated, or reordered. Something has to bridge that gap: chop the bytes into packets, number them, get a receipt for each, and hand the bytes to the receiving program in the original order. That bridging work is what this lesson shows, packet by packet.

✗ Common misunderstanding: If I send() twice, the other side will recv() twice with the same boundaries.

Why that's wrong: TCP is a byte stream with no message boundaries. Two writes may arrive coalesced in one segment, and one write may be split across several.

Correct model: TCP guarantees the ORDER and completeness of bytes, never their grouping. Applications must frame their own messages (length prefixes, delimiters).

The packets prove it: In the Nagle lesson three separate keystrokes arrive inside ONE segment — the receiver cannot tell where the writes were.

Watch these fields in the lab: tcp.sequenceNumber

write() / send()
The system call your program makes to hand bytes to TCP. It returns as soon as TCP has COPIED the bytes into its send buffer — not when they arrive, and not when they're acknowledged. A successful write() is not a delivery receipt.
Send buffer
Kernel memory holding bytes TCP has accepted from your program but not yet had acknowledged. A copy stays here even after the segment is sent, because it may need retransmitting.
Segmentglossary
One TCP header plus the slice of the byte stream it carries. TCP chooses where the slices fall; your program has no say.
PSH flag
A hint from the sender's TCP that the receiver shouldn't sit on these bytes waiting for more — deliver them to the application now. It is a hint about timing, not a message boundary.

Watch these fields in the lab: tcp.flags.psh

✓ Concept check — before you open the packets

These test the idea, not the trace. You should be able to answer them from the explanation above.

An application calls write() three times: 10 bytes, 10 bytes, 10 bytes. What is the receiving application guaranteed about how it will read them?

write() returns successfully. What has actually been proven at that moment?

Now that you understand the concept, observe how it appears in the packet exchange.

The lab runs a real simulated capture — pause, step, click any packet, and inspect every byte.