Skip to content

hop 20 of 32 · 6 min

TCP: making an unreliable network look reliable

IP makes no promises. Packets may be lost, duplicated, or arrive out of order. TCP takes that and presents an ordered, reliable byte stream, and every mechanism it has exists to bridge that gap.

Opening a connection

code
Client                          Server
   |  SYN, seq=x                   |
   |------------------------------>|
   |  SYN-ACK, seq=y, ack=x+1      |
   |<------------------------------|
   |  ACK, ack=y+1                 |
   |------------------------------>|

Three messages, not two, because a connection is two independent streams and each direction needs its sequence number acknowledged. After two messages the client knows both arrived; the server does not yet know its own reply got through.

Sequence numbers and acknowledgements

Every byte is numbered. The receiver acknowledges the next byte it expects. A gap means something was lost, and three duplicate acknowledgements for the same byte tell the sender to resend immediately rather than wait for a timeout.

Flow control

The receiver advertises a window: how much it can accept right now. The sender may have that much unacknowledged data in flight and no more. This stops a fast sender drowning a slow receiver.

Throughput is limited by window divided by round trip time:

code
64 KB window, 100 ms RTT
524,288 bits / 0.1 s = about 5.2 Mbps

On a 100 Mbps link that uses 5 percent of it. This is the bandwidth-delay product, and it is why window scaling exists: filling that link needs a window of about 1.25 MB, far past what the original 16-bit field could express.

Congestion control

Flow control protects the receiver. Congestion control protects the network. TCP starts slow, doubles its rate each round trip until loss, then backs off sharply and grows carefully. Loss is treated as the signal that the network is full.

TCP: making an unreliable network look reliable