TCP State Machine
What it is
TCP connections move through named states. A state and an event together decide the next state and actions. This challenge models those decisions without real sockets or timers. The opening and closing paths are different, so work from the state diagram.
The core idea
Opening requires both peers to agree that the connection is ready. Closing is more complex because each direction can finish at a different time. A local close, a peer close, and a simultaneous close need different paths.
Named states make these partial agreements explicit. TIME_WAIT helps keep delayed old packets out of a new connection. The cost of this safety is extra state and a wait before resources can be reused.
Where you meet this
- RFC 9293 is today's TCP standard. It replaced RFC 793 and keeps the state diagram. It says the side that closes first must stay in
TIME-WAITfor two maximum segment lifetimes, so its lastACKcan arrive and old packets cannot confuse a new connection. (RFC 9293) ss, the Linux socket tool, can filter connections by these same states:established,syn-sent,time-wait,close-wait, and the rest. (ss(8))- Linux connection tracking (netfilter) keeps a timeout per TCP state, for example
nf_conntrack_tcp_timeout_time_waitandnf_conntrack_tcp_timeout_close_wait. (nf_conntrack sysctl)
When to choose it: an explicit table of "in this state, this event leads to this state and these actions" fits any protocol with a fixed set of steps, like a handshake, a payment flow, or an order's life.
When not to: the logic has only one or two steps. A few flags are simpler there. Once flags start to combine in ways nobody planned for, a named state for each case is easier to check.
Common bugs
- Skipping
TIME_WAIT. - Treating a simultaneous close as an ordinary acknowledgement.
- Confusing a local close with a peer close.
- Returning the right state but forgetting an action such as
send_ack. - Crashing on an unexpected event instead of following the specified response.
- Changing state for an event that should be ignored.
Check it yourself
Trace local close, peer close, and simultaneous close separately. At every step, check both the next state and the emitted actions. Also test reset events and events that should do nothing.
Keep it fast
A simple state-and-event table or switch avoids building new dispatch objects on every call.
Learn more
RFC 793 includes the state diagram. RFC 1122 clarifies edge cases. TCP/IP Illustrated walks through real opening and closing packets.