Hacker DirectoryHacker Directory

WEB / WEB-04.02

TCP data transfer and loss management

Reconstruct a stream from sequence ranges and distinguish ACKs, retransmission and two sending budgets.

CORE · RED · BLUE · ARTIFACT · PRACTICE

1. Core · Mechanism

Read every scenario without motion

Ordered arrival

  1. Established byte context

    A completed handshake is selected; both peers are ready for transfer.

    Client transport
    ESTABLISHED; UNA=1001; NXT=1001
    Server transport
    ESTABLISHED; RCV.NXT=1001; contiguous=empty; app unread
  2. Local segmentation and sender bookkeeping

    NOTES! is divided into two selected segments. Sender bookkeeping is not proof of peer receipt.

    Client transport
    ESTABLISHED; UNA=1001; NXT=1007; flight=6; segments prepared
    Server transport
    ESTABLISHED; RCV.NXT=1001; contiguous=empty; app unread
  3. NO arrived at server

    The receiver updates ranges and contiguous prefix; the application has not read them yet.

    Client transport
    ESTABLISHED; UNA=1001; NXT=1007; flight=6; segments prepared
    Server transport
    ESTABLISHED; RCV.NXT=1003; contiguous=NO; held=empty; app unread
  4. ACK 1003 arrived at client

    The ACK updates sender transport knowledge, not business-success evidence.

    Client transport
    ESTABLISHED; UNA=1003; NXT=1007; ACK received=1003; flight=4
    Server transport
    ESTABLISHED; RCV.NXT=1003; contiguous=NO; held=empty; app unread
  5. TES! arrived at server

    The receiver updates ranges and contiguous prefix; the application has not read them yet.

    Client transport
    ESTABLISHED; UNA=1003; NXT=1007; ACK received=1003; flight=4
    Server transport
    ESTABLISHED; RCV.NXT=1007; contiguous=NOTES!; held=empty; app unread
  6. ACK 1007 arrived at client

    The ACK updates sender transport knowledge, not business-success evidence.

    Client transport
    ESTABLISHED; UNA=1007; NXT=1007; ACK received=1007; flight=0
    Server transport
    ESTABLISHED; RCV.NXT=1007; contiguous=NOTES!; held=empty; app unread
  7. Application local read

    The application consumes bytes locally; this is not another network transfer or persistent commit.

    Client transport
    ESTABLISHED; UNA=1007; NXT=1007; ACK received=1007; flight=0
    Server transport
    ESTABLISHED; RCV.NXT=1007; contiguous=NOTES!; app read=NOTES!; commit unmodeled

Reordered arrival

  1. Established byte context

    A completed handshake is selected; both peers are ready for transfer.

    Client transport
    ESTABLISHED; UNA=1001; NXT=1001
    Server transport
    ESTABLISHED; RCV.NXT=1001; contiguous=empty; app unread
  2. Local segmentation and sender bookkeeping

    NOTES! is divided into two selected segments. Sender bookkeeping is not proof of peer receipt.

    Client transport
    ESTABLISHED; UNA=1001; NXT=1007; flight=6; segments prepared
    Server transport
    ESTABLISHED; RCV.NXT=1001; contiguous=empty; app unread
  3. TES! arrived at server

    The receiver updates ranges and contiguous prefix; the application has not read them yet.

    Client transport
    ESTABLISHED; UNA=1001; NXT=1007; flight=6; segments prepared
    Server transport
    ESTABLISHED; RCV.NXT=1001; contiguous=empty; held=[1003,1007); app unread
  4. ACK 1001 arrived at client

    The ACK updates sender transport knowledge, not business-success evidence.

    Client transport
    ESTABLISHED; UNA=1001; NXT=1007; ACK received=1001; flight=6
    Server transport
    ESTABLISHED; RCV.NXT=1001; contiguous=empty; held=[1003,1007); app unread
  5. NO arrived at server

    The receiver updates ranges and contiguous prefix; the application has not read them yet.

    Client transport
    ESTABLISHED; UNA=1001; NXT=1007; ACK received=1001; flight=6
    Server transport
    ESTABLISHED; RCV.NXT=1007; contiguous=NOTES!; held=empty; app unread
  6. ACK 1007 arrived at client

    The ACK updates sender transport knowledge, not business-success evidence.

    Client transport
    ESTABLISHED; UNA=1007; NXT=1007; ACK received=1007; flight=0
    Server transport
    ESTABLISHED; RCV.NXT=1007; contiguous=NOTES!; held=empty; app unread
  7. Application local read

    The application consumes bytes locally; this is not another network transfer or persistent commit.

    Client transport
    ESTABLISHED; UNA=1007; NXT=1007; ACK received=1007; flight=0
    Server transport
    ESTABLISHED; RCV.NXT=1007; contiguous=NOTES!; app read=NOTES!; commit unmodeled

Selected RTO recovery

  1. Established byte context

    A completed handshake is selected; both peers are ready for transfer.

    Client transport
    ESTABLISHED; UNA=1001; NXT=1001
    Server transport
    ESTABLISHED; RCV.NXT=1001; contiguous=empty; app unread
  2. Local segmentation and sender bookkeeping

    NOTES! is divided into two selected segments. Sender bookkeeping is not proof of peer receipt.

    Client transport
    ESTABLISHED; UNA=1001; NXT=1007; flight=6; segments prepared
    Server transport
    ESTABLISHED; RCV.NXT=1001; contiguous=empty; app unread
  3. TES! arrived at server

    The receiver updates ranges and contiguous prefix; the application has not read them yet.

    Client transport
    ESTABLISHED; UNA=1001; NXT=1007; flight=6; segments prepared
    Server transport
    ESTABLISHED; RCV.NXT=1001; contiguous=empty; held=[1003,1007); app unread
  4. ACK 1001 arrived at client

    The ACK updates sender transport knowledge, not business-success evidence.

    Client transport
    ESTABLISHED; UNA=1001; NXT=1007; ACK received=1001; flight=6
    Server transport
    ESTABLISHED; RCV.NXT=1001; contiguous=empty; held=[1003,1007); app unread
  5. Local RTO decision

    The earlier NO arrival was absent. Selected timer expiry prepares retransmission; the cause is not measured.

    Client transport
    ESTABLISHED; UNA=1001; local RTO=1000ms expired; backoff=2000ms; resend NO at 1001
    Server transport
    ESTABLISHED; RCV.NXT=1001; contiguous=empty; held=[1003,1007); app unread
  6. NO arrived at server

    The receiver updates ranges and contiguous prefix; the application has not read them yet.

    Client transport
    ESTABLISHED; UNA=1001; local RTO=1000ms expired; backoff=2000ms; resend NO at 1001
    Server transport
    ESTABLISHED; RCV.NXT=1007; contiguous=NOTES!; held=empty; app unread
  7. ACK 1007 arrived at client

    The ACK updates sender transport knowledge, not business-success evidence.

    Client transport
    ESTABLISHED; UNA=1007; NXT=1007; ACK received=1007; flight=0
    Server transport
    ESTABLISHED; RCV.NXT=1007; contiguous=NOTES!; held=empty; app unread
  8. Application local read

    The application consumes bytes locally; this is not another network transfer or persistent commit.

    Client transport
    ESTABLISHED; UNA=1007; NXT=1007; ACK received=1007; flight=0
    Server transport
    ESTABLISHED; RCV.NXT=1007; contiguous=NOTES!; app read=NOTES!; commit unmodeled

Window credit

  1. Zero window is known

    Unscaled rwnd=0,cwnd=4,flight=0 gives no ordinary new-data budget.

    Client transport
    known rwnd=0; cwnd=4; budget=0
    Server transport
    advertised rwnd=0; app buffer occupied
  2. Local new-data gate

    Ordinary new data is blocked; the connection remains open. The probe algorithm is not modeled.

    Client transport
    new data held; known rwnd=0; budget=0
    Server transport
    advertised rwnd=0; app buffer occupied
  3. Receiver local consumption

    Selected application consumption frees buffer space. The receiver prepares window=6; the client does not yet know.

    Client transport
    new data held; known rwnd=0; budget=0
    Server transport
    local window update prepared: rwnd=6
  4. Window update arrival

    ACK/window information reached the sender. min(6,4)−0=4 new-data bytes are available, without an invented data arrival.

    Client transport
    known rwnd=6; cwnd=4; flight=0; budget=4
    Server transport
    local window update prepared: rwnd=6

ACTORS · STATE · DATA FLOW

Sequence numbers identify byte positions

After the handshake the client stream starts at 1001. ASCII NOTES! contains six bytes: segment SEQ=1001 carries NO, and SEQ=1003 carries TES!. Their ranges are [1001,1003) and [1003,1007). ACK=1007 reports reception of all contiguous bytes before 1007, excluding that position.

Sequence and acknowledgment progress independently in each direction; the ACK field refers to the next expected position in the opposite direction. Real TCP uses 32-bit sequence arithmetic modulo 2^32. This small example does not cross wraparound. ASCII makes byte count explicit rather than confusing it with UTF-8 character count.

Segmentation does not redefine application messages

TCP divides the byte stream into segments carried in IP datagrams, and the receiver reconstructs the stream from sequence ranges. Sizes depend on MSS, path MTU, buffering and implementation decisions. Our two/four-byte segments simplify arithmetic; they are neither real Internet MSS values nor observed browser packetization.

If TES! arrives first, our receiver holds it within the selected receive window. Before NO arrives there is no contiguous prefix and ACK stays at 1001. Once NO arrives the prefix becomes NOTES! and ACK advances to 1007. The model selects out-of-order buffering without asserting identical buffering policies or ACK timing across stacks.

Retransmission does not allocate new byte positions

The sender tracks bytes not yet acknowledged. In our selected branch NO arrival is absent, TES! arrives and the ACK does not advance. A local RTO expiration resends the earliest unacknowledged range [1001,1003). The same NO uses the same sequence positions, creating neither a new application message nor two extra stream bytes.

In RFC 6298, RTO relates to RTT estimates and variation, with backoff after timeout. Our 1000-to-2000 ms change is selected arithmetic, not an OS default. A missing ACK or retransmission alone does not prove data loss: delay, reordering or ACK loss can affect what the sender knows.

Fast recovery and timers have different triggers

The baseline RFC 5681 fast-retransmit profile uses three qualifying duplicate ACKs as a loss indication before timer expiry. One repeated ACK is not that threshold; details such as window changes matter to the definition. SACK and newer loss recovery mechanisms can use other information, and the scene does not execute them.

ACK timing need not be one immediate ACK per segment; delayed acknowledgments are possible. Our ACK arrivals are selected for clear arithmetic. Claims that a real stack uses Reno or a particular millisecond timer require separate implementation evidence.

Flow control protects the receiver; congestion control the path

rwnd represents receive-window capacity while cwnd limits outstanding data according to the sender’s congestion control. In our simple unscaled snapshot, new-data budget is max(0,min(rwnd,cwnd)−flightBytes). With rwnd=6,cwnd=8,flight=2 it is four bytes; with rwnd=16,cwnd=4,flight=2 it is two.

rwnd=0 may reflect application-buffer pressure rather than connection closure. Ordinary new data is blocked; zero-window probing is separate. Slow start and congestion avoidance adjust cwnd using feedback, and loss/ECN signals influence sending. This lesson teaches the distinction and selected budget without reducing all congestion algorithms or pacing to one rule.

Transport receipt and application read are separate events

The receiver can have all bytes in its TCP buffer before the application reads them. ACK 1007 does not eliminate that distinction. The scene’s final local step illustrates consumption of NOTES!, without a network reply or database commit.

Choose the evidence required for success: contiguous transport bytes, completed application framing, handler outcome and persistent storage are separate events. Transport retransmission and application-level operation retries have different scopes.

2. Red · Trust & Impact

Read every scenario without motion

Prefix gap

  1. The transport-information kind was selected

    The first segment carries TES! starting at seq 1003. The receiver may retain that range, but preceding NO bytes are missing. Seeing a high SEQ does not close the gap.

    Transport evidence
    held[1003,1007] / gap1001
    Prefix / budget gate
    No acceptance gate
    Business acceptance
    No business outcome
  2. The false-completion gate stopped

    rcvNxt=1001, ack=1001 and contiguous stays empty. The application prefix is not declared complete before the gap closes.

    Transport evidence
    held[1003,1007] / gap1001
    Prefix / budget gate
    ACK=1001 / prefix empty
    Business acceptance
    No business outcome
  3. New information arrives under a separate condition

    NO brings two bytes starting at seq 1001 and closes the gap. Together with retained TES!, the contiguous prefix becomes NOTES! and the next expected value and ACK advance to 1007. Arrival order differs from byte order.

    Transport evidence
    Prefix NOTES! / ACK1007
    Prefix / budget gate
    ACK=1001 / prefix empty
    Business acceptance
    No business outcome
  4. An ACK is not an application commit

    ackEvidence supplies allThrough1006ReceivedAtTransport=true and applicationReadOrCommitProven=false. Transport bytes, application reading and persistence commit are separate acceptance stages.

    Transport evidence
    Prefix NOTES! / ACK1007
    Prefix / budget gate
    ACK=1001 / prefix empty
    Business acceptance
    Transport received / commit unknown
  5. RTO does not select a root cause

    Selected RTO expiry reflects missing ACK information at the sender; missingArrivalCause=not-determined remains. The 1000→2000 ms teaching values are not OS defaults or measured timeouts.

    Transport evidence
    Prefix NOTES! / ACK1007
    Prefix / budget gate
    Timer expired / cause unknown
    Business acceptance
    Transport received / commit unknown
  6. The bounded conclusion was retained

    Gap closure supports an ordered prefix; retransmitted NO uses the same sequence and does not duplicate the byte stream. Business success still needs separate evidence.

    Transport evidence
    Prefix NOTES! / ACK1007
    Prefix / budget gate
    Timer expired / cause unknown
    Business acceptance
    PASS: contiguous prefix / app unknown

Send budget

  1. The transport-information kind was selected

    In the congestion-limited example, receiver window is 16 and congestion window is 4 bytes, with 2 bytes already in flight. Even ample receiver space can leave the sender limited by congestion conditions.

    Transport evidence
    rwnd16 / cwnd4 / flight2
    Prefix / budget gate
    No acceptance gate
    Business acceptance
    No business outcome
  2. The false-completion gate stopped

    min(rwnd, cwnd)−flightBytes gives 2 bytes for this snapshot. rwnd=16 does not justify 14 bytes; a full sending scheduler remains out of scope.

    Transport evidence
    rwnd16 / cwnd4 / flight2
    Prefix / budget gate
    Budget=2
    Business acceptance
    No business outcome
  3. New information arrives under a separate condition

    The separate zero-window example has no new-data budget because rwnd is zero. Once the advertised window update reaches the sender, rwnd 6, cwnd 4 and flight 0 give a 4-byte budget. This is not a continuation of the preceding congestion-limited snapshot.

    Transport evidence
    Zero=0 / update=4
    Prefix / budget gate
    Budget=2
    Business acceptance
    No business outcome
  4. Sending allowance is not receipt

    The min(rwnd, cwnd) minus flight calculation limits how many new bytes the sender may send. A budget of 2 or 4 bytes proves neither transmission, ACK receipt nor application reading.

    Transport evidence
    Zero=0 / update=4
    Prefix / budget gate
    Budget=2
    Business acceptance
    Budget ≠ transmission or receipt
  5. Window limits have different owners

    rwnd is the capacity advertised by the receiver; cwnd is the sender's congestion limit. Subtracting flight 2 in the congestion-limited example leaves 2 bytes. This branch contains no timer expiry or retransmission event.

    Transport evidence
    Zero=0 / update=4
    Prefix / budget gate
    Congestion-limited budget: 2 bytes
    Business acceptance
    Budget ≠ transmission or receipt
  6. The bounded conclusion was retained

    Receiver/congestion budgets stay distinct; zero-window is not evidence of application maliciousness. No real pacing, window scaling or service-health outcome is added.

    Transport evidence
    Zero=0 / update=4
    Prefix / budget gate
    Congestion-limited budget: 2 bytes
    Business acceptance
    Budget calculated / delivery unknown

ASSUMPTION · BOUNDARY · CONTROL

Broken assumption: the largest SEQ proves all earlier data

Seeing a later segment does not fill a gap. When TES! arrives first, the prefix is empty and ACK=1001. Ignoring gaps can produce false delivery evidence.

Keep received ranges separate from the contiguous prefix. Later bytes join ordered delivery only when the gap closes.

Broken assumption: timeout locates the failure

RTO reflects the sender lacking new acknowledgment information, not a standalone diagnosis of the peer application or a particular router. The broken condition is treating a timer observation as proof of cause.

Separate data arrivals, ACK arrivals and sender timer events. The artifact leaves the missing-arrival cause undetermined.

Broken assumption: large rwnd always permits fast sending

Even with free receiver capacity, cwnd or another sending constraint can be tighter. Conflating rwnd and cwnd mixes path pressure with receiver pressure.

The control is distinct variables, byte units and outstanding data. Treating a TCP ACK as business success likewise crosses the transport boundary.

3. Blue · Secure development & defense

Read every scenario without motion

Ordered ledger

  1. Exclusive ends were calculated

    NO carries two bytes from seq 1001 and ends exclusively at 1003. TES! carries another four bytes to 1007. NOTES! is ASCII, so each character occupies one byte here; this is not assumed for Unicode.

    Byte-range evidence
    [1001,1003) + [1003,1007)
    Prefix calculation
    No prefix calculation
    Recovery review
    No verdict
  2. The first-arrival prefix was determined

    When NO arrives first, the contiguous prefix is NO. The receiver expects the next byte at 1003 and acknowledges 1003. The application has not consumed it yet; a transport prefix does not prove an application read.

    Byte-range evidence
    [1001,1003) + [1003,1007)
    Prefix calculation
    Contiguous NO / ACK1003
    Recovery review
    No verdict
  3. The second arrival completed the prefix

    TES! arriving in order gives contiguous=NOTES!, rcvNxt=1007 and ACK 1007. Combining segments does not create an application-message boundary.

    Byte-range evidence
    [1001,1003) + [1003,1007)
    Prefix calculation
    Contiguous NOTES! / ACK1007
    Recovery review
    No verdict
  4. The separate RTO example keeps byte positions

    A separate retransmission example is now compared: NO reuses the same byte range starting at earliestUnacknowledgedSeq 1001. This does not add a resend after the completed receive ledger above, nor append another NO to the stream.

    Byte-range evidence
    Retransmission [1001,1003) unchanged
    Prefix calculation
    Contiguous NOTES! / ACK1007
    Recovery review
    No verdict
  5. ACK arrival and local timer were separated

    In this separate RTO example, timerEventCause is supplied as selected-local-expiry-not-measured. Data at the receiver does not prove ACK arrival at the sender. An actual diagnosis needs sender timer evidence and the relevant ACK observation point; missingArrivalCause remains unknown.

    Byte-range evidence
    Retransmission [1001,1003) unchanged
    Prefix calculation
    Contiguous NOTES! / ACK1007
    Recovery review
    Separate receiver / sender knowledge
  6. The recovery result retained its scope

    Ordered and reordered supplied ledgers reach the same NOTES! bytes. Receive-prefix arithmetic consistency tests no real congestion algorithm, network-loss diagnosis or business commit.

    Byte-range evidence
    Retransmission [1001,1003) unchanged
    Prefix calculation
    Contiguous NOTES! / ACK1007
    Recovery review
    Byte arithmetic agrees / loss cause unknown

Reordered ledger

  1. Exclusive ends were calculated

    NO carries two bytes from seq 1001 and ends exclusively at 1003. TES! carries another four bytes to 1007. NOTES! is ASCII, so each character occupies one byte here; this is not assumed for Unicode.

    Byte-range evidence
    [1001,1003) + [1003,1007)
    Prefix calculation
    No prefix calculation
    Recovery review
    No verdict
  2. The first-arrival prefix was determined

    TES! arriving first gives held[1003, 1007], empty contiguous and ACK 1001. ACK is the first missing position, not the largest observed SEQ.

    Byte-range evidence
    [1001,1003) + [1003,1007)
    Prefix calculation
    Held TES! / ACK1001
    Recovery review
    No verdict
  3. The second arrival completed the prefix

    NO closes the gap, empties heldRanges and gives contiguous=NOTES! with ACK 1007. Out-of-order buffering is a selected permitted condition, not every implementation’s strategy.

    Byte-range evidence
    [1001,1003) + [1003,1007)
    Prefix calculation
    Contiguous NOTES! / ACK1007
    Recovery review
    No verdict
  4. The separate RTO example keeps byte positions

    A separate retransmission example is now compared: NO reuses the same byte range starting at earliestUnacknowledgedSeq 1001. This does not add a resend after the completed receive ledger above, nor append another NO to the stream.

    Byte-range evidence
    Retransmission [1001,1003) unchanged
    Prefix calculation
    Contiguous NOTES! / ACK1007
    Recovery review
    No verdict
  5. ACK arrival and local timer were separated

    In this separate RTO example, timerEventCause is supplied as selected-local-expiry-not-measured. Data at the receiver does not prove ACK arrival at the sender. An actual diagnosis needs sender timer evidence and the relevant ACK observation point; missingArrivalCause remains unknown.

    Byte-range evidence
    Retransmission [1001,1003) unchanged
    Prefix calculation
    Contiguous NOTES! / ACK1007
    Recovery review
    Separate receiver / sender knowledge
  6. The recovery result retained its scope

    Ordered and reordered supplied ledgers reach the same NOTES! bytes. Receive-prefix arithmetic consistency tests no real congestion algorithm, network-loss diagnosis or business commit.

    Byte-range evidence
    Retransmission [1001,1003) unchanged
    Prefix calculation
    Contiguous NOTES! / ACK1007
    Recovery review
    Byte arithmetic agrees / loss cause unknown

IMPLEMENTATION · SECURITY CONTROL · VERIFICATION

Complete the byte ledger by hand

Compute SEQ, payload-byte length and exclusive end. In the reordered branch record held ranges, then choose the first missing position as the ACK rather than the greatest position seen.

Rebuild the prefix through 1007 when NO fills the gap. Verify that retransmission at the same SEQ does not increase stream length.

Evaluate both budgets together

Compute receiver-limited, congestion-limited and zero-window rows. The selected window update reaches the sender through ACK arrival; local receiver-buffer consumption does not instantly update client knowledge.

This budget is not a full sending scheduler. Actual pacing, SWS/Nagle, scaling and congestion profiles require implementation evidence.

An application producer must respect its own buffering boundary too. For example, when Node.js Writable.write returns false, stop producing more chunks and resume after drain. This signal concerns application buffering, not a value identical to the artifact’s rwnd or cwnd. Verify both producer pausing with a slow consumer and resuming when capacity becomes available. A drain event does not establish that the remote application read, processed or persisted NOTES!.

Separate observations from business outcomes

Ordered, reordered and selected RTO recovery paths end with the same NOTES! bytes while arrival order and sender knowledge differ. Explaining the separate application read is a key boundary.

This inert ledger is not a network measurement. It supports reasoning about byte arithmetic and state ownership; actual implementation behavior requires separate validation.

NOW APPLY IT TO THE CASE

Which information do received ranges, contiguous prefixes and sender budgets keep separate?

NOTES! is carried in two segments. When TES! arrives first, the contiguous prefix remains incomplete until NO arrives. rwnd and cwnd impose different sending limits; a transport ACK does not prove application commit.

Where does the connection carrying the response differ from application outcome? Do not substitute network or transport evidence for body-parsing or DOM success.

Open the related case file ↗

READ THE EXAMPLE TOGETHER

Byte ranges, ACK and send-budget ledger

Select a field and examine what it supports and where the evidence ends.

Read the raw artifact and field explanations
{
  "context": {
    "protocol": "TCP",
    "client": "192.0.2.10:51000",
    "server": "198.51.100.200:443",
    "bothStates": "ESTABLISHED",
    "serverInitialRcvNxt": 1001,
    "senderInitialUna": 1001,
    "senderFinalNxt": 1007
  },
  "bytes": "NOTES!",
  "encoding": "ASCII; one byte per character",
  "segments": [
    {
      "seq": 1001,
      "payload": "NO",
      "payloadBytes": 2,
      "exclusiveEnd": 1003
    },
    {
      "seq": 1003,
      "payload": "TES!",
      "payloadBytes": 4,
      "exclusiveEnd": 1007
    }
  ],
  "orderedArrivals": [
    {
      "segmentIndex": 0,
      "rcvNxt": 1003,
      "ack": 1003,
      "contiguous": "NO",
      "applicationConsumed": false
    },
    {
      "segmentIndex": 1,
      "rcvNxt": 1007,
      "ack": 1007,
      "contiguous": "NOTES!",
      "applicationConsumed": false
    }
  ],
  "reorderedArrivals": [
    {
      "segmentIndex": 1,
      "rcvNxt": 1001,
      "ack": 1001,
      "heldRanges": [
        [
          1003,
          1007
        ]
      ],
      "contiguous": ""
    },
    {
      "segmentIndex": 0,
      "rcvNxt": 1007,
      "ack": 1007,
      "heldRanges": [],
      "contiguous": "NOTES!"
    }
  ],
  "retransmission": {
    "profile": "selected RFC6298 RTO branch; no SACK/timestamp or modern loss algorithm execution",
    "earliestUnacknowledgedSeq": 1001,
    "retransmittedPayload": "NO",
    "sequencePreserved": true,
    "selectedRtoMsBefore": 1000,
    "selectedRtoMsAfter": 2000,
    "elapsedSincePreviousTransmissionMs": 1000,
    "timerEventCause": "selected-local-expiry-not-measured",
    "missingArrivalCause": "not-determined"
  },
  "sendBudgetCases": [
    {
      "label": "receiver-limited",
      "rwnd": 6,
      "cwnd": 8,
      "flightBytes": 2,
      "newDataBudget": 4
    },
    {
      "label": "congestion-limited",
      "rwnd": 16,
      "cwnd": 4,
      "flightBytes": 2,
      "newDataBudget": 2
    },
    {
      "label": "zero-window",
      "rwnd": 0,
      "cwnd": 4,
      "flightBytes": 0,
      "newDataBudget": 0
    },
    {
      "label": "selected-window-update",
      "rwnd": 6,
      "cwnd": 4,
      "flightBytes": 0,
      "newDataBudget": 4
    }
  ],
  "windowUnits": "unscaled bytes; selected simple snapshot, no pacing/SWS/Nagle/ACK clock implementation",
  "ackEvidence": {
    "allThrough1006ReceivedAtTransport": true,
    "applicationReadOrCommitProven": false,
    "separateApplicationRead": "local illustrative step, no business persistence claim"
  },
  "limits": {
    "moduloSequenceArithmetic": "not-crossed; no wraparound test",
    "outOfOrderBuffering": "selected permitted buffering within receive window",
    "checksumMssPmtuOffload": "omitted",
    "rtoAndCongestionValues": "teaching values, not OS defaults"
  }
}
segments
Half-open sequence ranges for ASCII payload.
reorderedArrivals
Received buffered range versus contiguous prefix.
retransmission
Bytes at the same positions and selected RTO backoff.
sendBudgetCases
rwnd/cwnd/flight distinction in an unscaled byte snapshot.
ackEvidence
TCP receipt is not proof of application read/commit.

Not a full TCP packet, socket or timer implementation. SACK, wraparound, checksums, offload and actual congestion profiles are not executed.

Two reality checks

ACK is one beyond the largest SEQ seen.

A cumulative ACK identifies the first missing position. Buffered later ranges need not advance it until the gap closes.

rwnd zero means the TCP connection is closed.

Ordinary new-data budget may be zero; connection state and zero-window probing are separate mechanisms.

YOUR TURN

Work through this story.

Predict the outcome, find the evidence boundary, and explain it in your own words.

The 1003–1007 segment arrives before 1001–1003. What is the cumulative ACK?

  1. 1001; it does not advance to 1007 before the gap closes.
  2. 1007; the largest observed segment end becomes the ACK.
Read the explained answer

1001; it does not advance to 1007 before the gap closes. — Later bytes may be held; the cumulative ACK indicates the byte following the contiguous received prefix.

For rwnd=16, cwnd=4 and flight=2, what is the new-data budget?

Selected lesson artifact fields; teaching example

sendBudgetCases[1]
{"label":"congestion-limited","rwnd":16,"cwnd":4,"flightBytes":2,"newDataBudget":2}
  1. 2 bytes; the congestion window limits it.
  2. 14 bytes; only rwnd-flight is used.
Read the explained answer

2 bytes; the congestion window limits it. — The selected simple calculation is min(16, 4)-2=2; the receiver’s 16-byte allowance does not override cwnd.

ACK 1007 was received. Has the application definitely read and durably stored NOTES!? Explain in relation to RTO retransmission.

Read the explained answer

ACK 1007 denotes contiguous transport receipt through 1006 in this model. It is not application-read/commit evidence. The RTO branch retransmits the earliest unacknowledged bytes with the same sequence; timer expiry alone does not establish where loss occurred.

□ I did not count an ACK as an application commit.

□ I preserved retransmit sequence and the uncertain loss cause.

Open the application console · request / response / browser
Also open request, URL, cookie and DOM examples

Sources and scope