tcp connection lifecycle - establishment and termination
on this page
learning objectives
after this guide, you will understand:
- the three-way handshake process
- tcp connection states and transitions
- option negotiation during connection setup
- graceful connection termination
- abnormal termination scenarios
- time-wait state purpose
connection establishment
three-way handshake
tcp uses a three-way handshake to establish connections, synchronize sequence numbers, and negotiate parameters:
Connection establishment process showing state transitions and segment exchange between client and server.
detailed steps
step 1: syn (client → server)
- client chooses initial sequence number (isn)
- sends syn segment with isn
- includes tcp options for negotiation
- transitions to syn-sent state
step 2: syn-ack (server → client)
- server acknowledges client’s syn (ack = client_isn + 1)
- chooses its own isn
- sends syn with its isn
- includes tcp options response
- transitions to syn-received state
step 3: ack (client → server)
- client acknowledges server’s syn (ack = server_isn + 1)
- transitions to established state
- may include data in this segment
- server transitions to established upon receipt
sequence number selection
initial sequence numbers (isn) should be:
- unpredictable - security against spoofing
- monotonic - increasing over time
- unique - avoid confusion with old connections
modern systems use:
ISN = M + F(localhost, localport, remotehost, remoteport, secret)
# M = 4-microsecond timer
# F = cryptographic hash function
option negotiation
during the handshake, tcp endpoints negotiate capabilities:
common tcp options
tl;dr
Option | Purpose | When Sent | Size |
MSS | Maximum Segment Size | SYN only | 4 bytes |
Window Scale | Extend window > 64KB | SYN only | 3 bytes |
SACK Permitted | Enable selective ack | SYN only | 2 bytes |
Timestamps | RTT measurement | All segments | 10 bytes |
TFO Cookie | Fast Open data | SYN | 6-18 bytes |
option negotiation rules
- syn-only options - must be in syn segments only
- mutual agreement - both sides must support
- no renegotiation - options fixed after handshake
- fallback behavior - graceful degradation if not supported
example option exchange
Shows how TCP options are negotiated during the three-way handshake, with each side proposing capabilities.
connection states
tcp connections progress through well-defined states:
state transition diagram
Complete state machine showing all TCP states and transitions during connection establishment, data transfer, and termination.
state descriptions
tl;dr
State | Description | Can Send | Can Receive |
CLOSED | No connection exists | No | No |
LISTEN | Waiting for connection request | No | SYN only |
SYN-SENT | Waiting for matching SYN | SYN | SYN, SYN-ACK |
SYN-RECEIVED | Waiting for confirming ACK | SYN-ACK | ACK |
ESTABLISHED | Connection open | Data | Data |
FIN-WAIT-1 | Waiting for FIN ACK | FIN | Data, ACK, FIN |
FIN-WAIT-2 | Waiting for FIN | No | Data, FIN |
CLOSE-WAIT | Waiting for close from app | Data | No |
LAST-ACK | Waiting for final ACK | FIN | ACK |
TIME-WAIT | Waiting for network to clear | ACK | Retransmitted FIN |
CLOSING | Simultaneous close | FIN | ACK |
connection termination
graceful close (four-way handshake)
tcp connections close gracefully with a four-way handshake:
Graceful connection close showing the four-step process and TIME-WAIT state to ensure reliable termination.
termination steps
step 1: initiator sends fin
- application calls close()
- tcp sends fin segment
- transitions to fin-wait-1
- can still receive data
step 2: receiver acknowledges fin
- sends ack for fin
- transitions to close-wait
- notifies application of eof
- can still send data
step 3: receiver sends fin
- application calls close()
- tcp sends fin segment
- transitions to last-ack
- no more data transfer
step 4: initiator acknowledges fin
- sends ack for fin
- enters time-wait state
- waits 2*msl before closing
- ensures final ack received
half-close
tcp supports half-close where one direction closes while other remains open:
# shutdown for writing but keep reading
shutdown(socket, SHUT_WR)
# useful for:
# - request/response protocols
# - signaling end of data
# - maintaining control channel
time-wait state
purpose
time-wait serves two critical functions:
- reliable termination - ensures final ack reaches peer
- connection incarnation protection - prevents old segments from new connections
duration
time-wait lasts 2*msl (maximum segment lifetime):
- typical msl = 30-120 seconds
- total wait = 60-240 seconds
- configurable via tcp_fin_timeout (linux)
implications
Key Highlights
- port exhaustion - rapid connection cycling can exhaust ports
- memory usage - each time-wait connection uses memory
- cannot reuse socket - must wait for timeout
- so_reuseaddr - allows bind to time-wait port (server)
avoiding time-wait
strategies to minimize time-wait accumulation:
- connection pooling - reuse long-lived connections
- let client close first - server avoids time-wait
- so_reuseaddr - allows immediate rebind
- tcp_tw_reuse - linux option for client connections
abnormal termination
reset (rst) scenarios
tcp uses rst flag for immediate termination:
tl;dr
Scenario | Cause | Result |
Port unreachable | No listener on port | RST sent immediately |
Abort connection | SO_LINGER with timeout=0 | RST instead of FIN |
Half-open detection | Peer crashed/rebooted | RST on unexpected segment |
Security violation | Invalid sequence numbers | RST to terminate |
Buffer overflow | No room for data | RST if cannot recover |
handling resets
# detect reset in application
try:
data = socket.recv(1024)
except ConnectionResetError:
print("Connection reset by peer")
# common causes to investigate:
# - application crash
# - firewall intervention
# - timeout/keepalive failure
# - explicit abort
simultaneous operations
simultaneous open
rare but possible - both ends initiate simultaneously:
Both endpoints actively initiate connection at the same time, resulting in a modified handshake sequence.
simultaneous close
both ends initiate close simultaneously:
Both endpoints initiate connection termination at the same time, leading to the CLOSING state.
connection establishment optimizations
tcp fast open (tfo)
allows data in syn packets to reduce latency:
Compares traditional three-way handshake with TCP Fast Open, showing how TFO reduces latency by including data in the SYN packet.
benefits:
- reduces latency by 1 rtt
- especially useful for short flows
- http requests can be sent with syn
limitations:
- requires application changes
- security considerations (replay attacks)
- limited deployment support
syn cookies
protects against syn flood attacks:
- don’t allocate state for syn-received
- encode state in isn
- reconstruct state from ack
# syn cookie generation
cookie = hash(client_ip, client_port, server_ip, server_port, secret) +
encoded_mss + timestamp
# validation on ack
if validate_cookie(ack_number - 1):
create_connection()
practical considerations
tuning parameters
# linux tcp connection parameters
# syn retries (default: 6)
net.ipv4.tcp_syn_retries = 3
# syn-ack retries (default: 5)
net.ipv4.tcp_synack_retries = 3
# fin timeout (default: 60)
net.ipv4.tcp_fin_timeout = 30
# time-wait reuse (careful!)
net.ipv4.tcp_tw_reuse = 1
# syn backlog size
net.ipv4.tcp_max_syn_backlog = 4096
monitoring connection states
# count connections by state
ss -ant | awk '{print $1}' | sort | uniq -c
# find time-wait connections
ss -ant state time-wait
# monitor syn_recv (possible syn flood)
watch -n 1 'ss -ant | grep SYN_RECV | wc -l'
# connection state distribution
netstat -ant | awk '/^tcp/ {print $6}' | sort | uniq -c
common issues and solutions
issue: connection timeout
symptoms: connection attempts fail after delay
causes:
- firewall dropping syn
- routing issues
- server not listening
- syn queue full
debugging:
# check if syn packets leaving
tcpdump -i any 'tcp[tcpflags] & tcp-syn != 0'
# verify route
traceroute -T -p 80 target.host
# check firewall
iptables -L -n -v
issue: time-wait accumulation
symptoms: cannot bind to port, port exhaustion
solutions:
- use connection pooling
- enable so_reuseaddr
- adjust tcp_tw_reuse (client)
- reduce tcp_fin_timeout
issue: half-open connections
symptoms: connections hang, resources leak
causes:
- peer crash without fin
- network partition
- firewall timeout
solutions:
- enable tcp keepalive
- application-level heartbeat
- monitor connection states
key takeaways
- three-way handshake establishes connection and synchronizes state
- option negotiation happens only during handshake
- connection states follow well-defined transitions
- graceful termination uses four-way handshake
- time-wait prevents connection confusion
- resets provide immediate termination
- various optimizations improve connection performance
next steps
- explore reliability mechanisms for data integrity
- study sliding window protocol for rate management
- examine tcp fast open for latency optimization