TCP Sequence Numbers, ACKs & Retransmission (RTO)
Client sends SYN to initiate connection
The client sends a SYN packet to the server to start the TCP three-way handshake. This packet has an initial sequence number (seq=1000).
send_packet(src='client', dst='server', seq=1000, flags=['SYN'])Server receives SYN and replies with SYN-ACK
The server receives the SYN, processes it, and replies with a SYN-ACK packet. The server's sequence number is 3000, and it acknowledges the client's SYN by setting ACK=1001.
send_packet(src='server', dst='client', seq=3000, ack=1001, flags=['SYN','ACK'])Client receives SYN-ACK and sends ACK
The client receives the SYN-ACK, processes it, and sends an ACK packet back to the server. The ACK acknowledges the server's SYN by setting ACK=3001.
send_packet(src='client', dst='server', seq=1001, ack=3001, flags=['ACK'])Client sends first data packet (seq=1001)
The client sends the first data packet with sequence number 1001 and payload 'Hello'.
send_packet(src='client', dst='server', seq=1001, ack=3001, flags=[], data='Hello')Server receives data and sends ACK (ack=1006)
The server receives the data packet with seq=1001 and payload 'Hello' (5 bytes). It sends an ACK with ack=1006, indicating it expects the next byte at 1006.
send_packet(src='server', dst='client', seq=3001, ack=1006, flags=['ACK'])Client sends second data packet (seq=1006)
The client sends the second data packet with sequence number 1006 and payload 'World'.
send_packet(src='client', dst='server', seq=1006, ack=3001, flags=[], data='World')Second data packet lost in transit (no ACK received)
The second data packet is lost and does not reach the server. The client waits for an acknowledgment but none arrives before the retransmission timeout (RTO).
# Packet lost, no ACK received; wait for RTORetransmission timeout (RTO) triggers resend of lost packet
The client's retransmission timer expires (RTO). It resends the lost data packet with seq=1006 and payload 'World'.
send_packet(src='client', dst='server', seq=1006, ack=3001, flags=['RTO'], data='World')Server receives retransmitted packet and sends ACK (ack=1011)
The server receives the retransmitted packet with seq=1006 and payload 'World'. It sends an ACK with ack=1011, confirming receipt of all data up to byte 1010.
send_packet(src='server', dst='client', seq=3001, ack=1011, flags=['ACK'])Client receives final ACK confirming all data received
The client receives the ACK with ack=1011, confirming all sent data has been received by the server. The connection is now fully synchronized and data transfer is complete.
# Client processes final ACKdef send_packet(src, dst, seq, ack=None, flags=None, data=None):
# STEP 1-10: Simulate sending TCP packets with sequence and acknowledgment numbers
packet = {'src': src, 'dst': dst, 'seq': seq, 'ack': ack, 'flags': flags or [], 'data': data}
# Normally send packet over network
return packet
# STEP 1
send_packet('client', 'server', seq=1000, flags=['SYN'])
# STEP 2
send_packet('server', 'client', seq=3000, ack=1001, flags=['SYN','ACK'])
# STEP 3
send_packet('client', 'server', seq=1001, ack=3001, flags=['ACK'])
# STEP 4
send_packet('client', 'server', seq=1001, ack=3001, data='Hello')
# STEP 5
send_packet('server', 'client', seq=3001, ack=1006, flags=['ACK'])
# STEP 6
send_packet('client', 'server', seq=1006, ack=3001, data='World')
# STEP 7
# Packet lost: no send_packet call
# STEP 8
send_packet('client', 'server', seq=1006, ack=3001, flags=['RTO'], data='World')
# STEP 9
send_packet('server', 'client', seq=3001, ack=1011, flags=['ACK'])
# STEP 10
# Client receives final ACK (no send_packet call needed)
Key Takeaways
This insight is hard to see from code alone because sequence and ACK numbers are abstract counters; visualization shows their flow and updates clearly.
Plain English explanation: when an ACK is not received in time, TCP resends the missing data to guarantee delivery.
Seeing the SYN, SYN-ACK, and ACK packets in sequence clarifies how TCP establishes connection state.
