TCP, simulated
TCP you can watch: two hosts and a bottleneck router with a queue, every segment a labelled packet — the handshake and its options, sequence and ACK numbers, windows, delayed ACKs and Nagle, the RFC 6298 timer, fast retransmit, NewReno and SACK, Reno vs CUBIC vs BBR with cwnd plotted, bufferbloat, long fat pipes, fairness between two flows, FIN, TIME_WAIT and RST — exportable as a pcap.
Added · updated 28 October 2026
Works with
- Packet capture viewer (mini Wireshark) NetworkOpen in packet viewer hands the simulated run there as a capture
How to use it
A TCP connection in miniature that runs in this page: a client, a server, and between them a
router whose queue feeds a slower link — the bottleneck. Every segment is a labelled packet
crossing the diagram (SYN seq=0 mss 1460 ws3 sack, 1461:2921, ACK 2921 S4381-5841), and the
congestion window, the round-trip time and the queue are plotted as they change. The rules follow
the RFCs (linked below); nothing here touches a real network.
I wanted one place to see why a big buffer makes a link feel slow, why a lost packet costs one round trip with SACK and three without it, and why two writes and a delayed ACK add 40 ms to every request. The congestion control is simplified, but each algorithm has the shape of the real one.
How to use it
Pick a scenario and press Start. Each step does something — connects, starts a transfer, drops a segment, cuts the link, switches congestion control — then plays until it has happened and pauses so you can read what happened and why, with links to the RFC section. Next step moves on, Back rewinds (the simulator is deterministic, so it replays the earlier steps), ⏭ jumps to the end of the step and Step ⇥ advances to the next single event. Space plays and pauses; → is the next step. The Playground has no script: connect, send and break things.
Speed scales everything: at 1× a tenth of a simulated second passes per real second, so a 40 ms
round trip takes 0.4 s to watch. Hop time slows the clock while a handshake segment, a FIN, an RST
or a small window’s segments are on the wire, so you can read them; bulk data moves on the
simulated clock. For the long scenarios (fairness, bufferbloat) use 4× or 8×, or ⏭. ⛶ Full
screen (or f) gives the diagram the whole window.
-
The diagram. Host A (and C, the second flow’s sender, in the fairness scenario) on the left; the router R with its queue drawn as slots filling from the right (the head of the queue), the link to the server B, and the return path for ACKs underneath. Each client card shows its state, the congestion control and its phase (slow start, congestion avoidance, CUBIC concave/convex, fast recovery, BBR’s mode), cwnd and ssthresh, SRTT and RTO, and a send strip: its sequence space from snd.una, with segments in flight, SACKed, judged lost and retransmitted, the black bar at una + min(cwnd, rwnd) and a red bar where the receive window is the limit. The server card shows rcv.nxt, the window it offers, unread data and out-of-order blocks, and a pending delayed ACK. Tap a host to connect, send, close or reset; tap the router to drop segments.
-
Do something. Connect and send (bulk, 100 kB, request/response rounds), close, reset; drop the next segment, three in a window, or everything for 300 ms; change loss, reordering, queue size, bandwidth, Nagle, delayed ACKs and how fast the receiving application reads — while it runs. ⬇ .pcap downloads the run so far as a capture taken at the sending host: open it in Wireshark,
tcpdump -r, or the site’s packet viewer. Frames carry real sequence and acknowledgement numbers, windows, options and SACK blocks; payloads are cut to a 128-byte snap length, astcpdump -s 128would. Open in packet viewer opens it straight in the packet capture viewer in a new tab, where the retransmissions and duplicate ACKs show up in its TCP analysis. -
Congestion window. cwnd and ssthresh over time for each flow, recovery shaded, with the path’s BDP and BDP + queue drawn.
-
RTT and queue. Every RTT sample, SRTT (and the RTO if you tick it), and the router’s queue.
-
Time–sequence graph. The last 500 segments of flow 1, as Stevens drew them: bars for segments, red for retransmissions, the cumulative ACK as a step line, SACK blocks in teal.
-
Flows. Throughput, retransmissions, fast retransmits, timeouts, duplicate and partial ACKs, window probes, request latencies, and Jain’s fairness index when two flows share the link.
-
Retransmission timer. RFC 6298’s SRTT, RTTVAR and RTO for each end, with the formulas.
-
State machine. RFC 9293’s state diagram with each end’s state and last transition highlighted, and the full history.
-
Settings. Bandwidth, RTT, queue size, loss, reordering, congestion control per flow, a second flow and its RTT, MSS, initial window, receive buffer, reader speed, minimum RTO, delayed-ACK timer, MSL, and SACK, window scaling, delayed ACKs and Nagle on or off. Settings and the scenario are kept in the share link.
What it models
-
Connection set-up and teardown (RFC 9293): random ISNs (shown relative, as Wireshark does, or absolute), the three-way handshake with MSS, window scale (RFC 7323) and SACK-permitted (RFC 2018) options, SYN retransmission, FIN in both directions with FIN_WAIT_1/2, CLOSE_WAIT, LAST_ACK, CLOSING and TIME_WAIT for 2 × MSL, and RST on abort and for segments to a closed connection.
-
Windows. The sender is limited by min(cwnd, the peer’s receive window); the receiver offers its free buffer (scaled when window scaling was agreed), avoids silly windows (RFC 1122 §4.2.3.3), sends window updates as its application reads, and a sender facing a zero window sends probes.
-
ACKs (RFC 5681 §4.2, RFC 1122 §4.2.3.2): an ACK for every second full-size segment, otherwise after the delayed-ACK timer; at once for out-of-order data and when a hole is filled; piggybacked on data going the other way. Nagle (RFC 896) holds a small segment while an earlier small one is unacknowledged — the variant Linux uses — and TCP_NODELAY turns it off.
-
The retransmission timer (RFC 6298): SRTT, RTTVAR and RTO exactly as specified, a configurable minimum (200 ms like Linux by default; the RFC says 1 s), Karn’s algorithm, exponential back-off, go-back-N after a timeout with cwnd = 1 segment.
-
Loss recovery: fast retransmit on the third duplicate ACK and NewReno fast recovery with window inflation and partial ACKs (RFC 6582); with SACK, a scoreboard, IsLost and the pipe estimate of RFC 6675.
-
Congestion control. Reno: slow start from an initial window of 10 (RFC 6928) with byte counting (RFC 3465, L = 2), one segment per round trip in congestion avoidance, ssthresh = max(FlightSize/2, 2·MSS). CUBIC (RFC 9438): W(t) = C(t − K)³ + W_max with C = 0.4, β = 0.7, fast convergence and the Reno-friendly region. BBR (version 1, after Cardwell et al., BBR: Congestion-Based Congestion Control, 2016): delivery-rate samples, BtlBw as a 10-round windowed maximum, RTprop as a 10-second windowed minimum, STARTUP at a gain of 2/ln 2, DRAIN, PROBE_BW’s eight-phase gain cycle, PROBE_RTT, pacing and cwnd = 2 × BDP. cwnd only grows while it is the limit (as Linux does). Not modelled: HyStart, PRR, RACK-TLP, timestamps, ECN, BBR v2/v3, and BBR’s loss-recovery tweaks.
-
The path. One drop-tail queue at the bottleneck (no AQM), serialisation at the bottleneck rate, fixed propagation delay, random loss and reordering on the bottleneck link, injected drops and outages. ACKs come back over an uncongested path. A second flow can have its own RTT.
Related tools: TLS 1.3 and QUIC handshakes (what runs on top of this connection, and how QUIC saves the round trip), DHCP, ARP, NAT and routing (the layers below), latency numbers, a speed test for your own connection, load balancing and retries (queues and tail latency one level up), and Raft, simulated, which shares this tool’s simulator kit.
Runs in any current browser (Chrome, Edge, Firefox, Safari), on phones too; nothing to install.
Feedback is a gift. Something to improve, a feature to add, or a bug? Tell me.
Runs entirely in your browser; nothing you type leaves this page.