WEB / WEB-04.02
TCP data transfer and loss management
Reconstruct a stream from sequence ranges and distinguish ACKs, retransmission and two sending budgets.
1. Core · Mechanism
Read every scenario without motion
Ordered arrival
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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?
- 1001; it does not advance to 1007 before the gap closes.
- 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}
- 2 bytes; the congestion window limits it.
- 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
- RFC 9293 — Transmission Control Protocol (TCP)3.1 Header Format; 3.4 Sequence Numbers · 3.3.2 State Machine Overview; 3.5.3 Reset Processing; 3.6 Closing a Connection; 3.6.1 Half-Closed Connections · 3.7 Segmentation; 3.8.1 Retransmission Timeout; 3.8.6 Managing the Window
- RFC 5681 — TCP Congestion Control2 Definitions; 3.1 Slow Start and Congestion Avoidance · 3.2 Fast Retransmit/Fast Recovery
- RFC 6298 — Computing TCP’s Retransmission Timer2 The Basic Algorithm; 3 Taking RTT Samples · 5 Managing the RTO Timer
- RFC 5737 — IPv4 Address Blocks Reserved for Documentation3 Documentation Address Blocks
- Node.js Stream — Writable backpressureEvent: 'drain' · writable.write(chunk[, encoding][, callback])