TCP and UDP: delivering data reliably
IP delivers packets on a best-effort basis — some get lost, some arrive out of order. See how TCP builds a reliable stream on top, why UDP deliberately doesn’t, and how to choose between them.
In this lecture you will
- Explain how port numbers connect packets to the right application
- Describe how TCP achieves reliable, ordered delivery with sequence numbers, acknowledgements and retransmission
- Explain what flow control and congestion control protect
- Choose between TCP and UDP for a given use case
The network layer makes a modest promise: it will try to deliver each packet. Packets can still be dropped by a busy router, corrupted on a noisy link, duplicated, or overtaken by later packets that took a faster path. Applications need something better — or at least something predictable. That is the job of the transport layer, and its two main protocols make opposite trade-offs.
Ports: from machine to program
An IP address identifies a machine, but a server runs many programs at once. Port numbers identify which one a packet is for. Well-known services listen on standard ports:
| Port | Service |
|---|---|
| 22 | SSH — remote shell |
| 53 | DNS |
| 80 / 443 | HTTP / HTTPS |
| 5432 | PostgreSQL |
The client side uses a temporary ephemeral port chosen by the operating system, such as 51234. The combination of source IP, source port, destination IP, destination port and protocol uniquely identifies a conversation — which is how one server keeps thousands of connections apart.
UDP: send and forget
UDP (User Datagram Protocol) adds almost nothing to IP: source and destination ports, a length and a checksum — an 8-byte header. There is no connection, no acknowledgement and no retransmission. Each datagram is on its own.
That sounds primitive, but it is exactly right when:
- timeliness matters more than completeness — voice, video calls and online games would rather skip a lost frame than wait for it;
- the exchange is a single question and answer — such as a DNS lookup, where the client can simply ask again;
- the application wants its own reliability — QUIC, the transport under HTTP/3, runs on top of UDP and implements smarter recovery itself.
TCP: a reliable byte stream
TCP (Transmission Control Protocol) gives applications the illusion of a perfect pipe: bytes go in one end and come out the other, complete and in order. To build that on an unreliable network it uses a few mechanisms:
- Handshake
- SYN, SYN-ACK and ACK establish the connection and agree on starting sequence numbers.
- Sequence numbers
- Every byte in the stream is numbered, so the receiver can reorder segments and spot gaps.
- Acknowledgements
- The receiver reports the next byte it expects. Anything before that number has arrived safely.
- Retransmission
- If data isn’t acknowledged in time — or duplicate acknowledgements reveal a gap — the sender sends it again.
- Flow control
- The receiver advertises how much buffer space it has left, so a fast sender cannot overwhelm it.
- Congestion control
- The sender probes for available bandwidth and slows down sharply when loss suggests the network is overloaded.
Here is a complete connection, from the first SYN to the final ACK, with the sequence and acknowledgement numbers both sides actually exchange.
- SYNThe client picks a starting sequence number — here 100 — and sends a SYN. Its state becomes SYN_SENT; the server is LISTENing.
- SYN-ACK, ACKThe server replies with its own starting number (300) and acknowledges 101, the client’s number plus one. The client acknowledges 301. Both sides are now ESTABLISHED.
- Data and acknowledgementsThe client sends an 80-byte request starting at 101, so the server acknowledges 181: the next byte it expects. The 1,200-byte response is acknowledged with 1501.
- ClosingEach direction is closed separately. The client sends FIN, the server acknowledges it, then sends its own FIN, which the client acknowledges.
- TIME_WAITThe side that closed first waits in TIME_WAIT for a while, in case its final ACK was lost and the other side sends its FIN again. Busy servers can have thousands of connections in this state.
Watch the difference
Compare the two protocols, with and without a lost packet. Notice what TCP has to do before it sends any data, how acknowledgements expose the missing segment, and how UDP simply carries on.
Sequence numbers are simplified: real connections start from random values and send many segments before waiting for acknowledgements.
The lost TCP segment illustrates the key trade-off. Data after the gap cannot be handed to the application until the missing piece arrives — the whole stream waits. This is called head-of-line blocking, and it is one reason HTTP/3 moved to QUIC, which keeps separate streams independent.
Sharing the network: congestion control
How fast should a sender go? It cannot know the capacity of every link on the path, so TCP probes. Its congestion window limits how many segments may be unacknowledged at once. It starts small and doubles every round trip (slow start), then grows by one segment per round trip (congestion avoidance). When a segment is lost, TCP assumes the network is overloaded and backs off sharply — then starts probing again. The result is the famous sawtooth.
Compare Reno, which halves its window after a loss, with Tahoe, which restarts from one segment. Then add 1% random loss, as on a poor Wi-Fi link: TCP mistakes it for congestion and throughput collapses.
That last effect explains why a lossy link feels so much slower than its bandwidth suggests. Newer algorithms help: CUBIC, the Linux default, regrows its window much faster after a loss, and BBR, used by many large services, estimates the bottleneck bandwidth and round-trip time directly instead of treating every loss as congestion.
Choosing a transport
| Use case | Typical choice | Why |
|---|---|---|
| Web pages, APIs, file transfer, email, databases | TCP (or QUIC) | Every byte must arrive, in order |
| DNS lookups | UDP (TCP for large answers) | One small question and answer |
| Voice and video calls, live streaming, games | UDP | Late data is useless; low delay wins |
| Modern web (HTTP/3) | QUIC over UDP | Reliability without head-of-line blocking |
In practice you rarely pick a transport directly — you choose a protocol or library, and it chooses for you. But knowing what lies underneath explains many behaviors you will debug.
That completes the journey from lecture 1: names, layers, addresses, routes and transport. The next module goes deeper into the services built on top — DNS, HTTP and HTTPS — and the equipment that carries them.
Key takeaways
- IP gets packets to a machine; ports and the transport protocol get data to the right program.
- TCP numbers every byte, acknowledges what arrived and retransmits what didn’t — at the cost of extra round trips and delay.
- UDP sends independent datagrams with no connection or recovery — ideal when late data is useless or the application handles loss itself.
- Flow control protects the receiver; congestion control protects the network.
Check your understanding
4 questions · answers explainedQ1Why does TCP number the data it sends?
Q2A video call app loses a few packets. Why is UDP usually the better transport here?
Q3A connection attempt fails instantly with “connection refused”. What does that usually tell you?
Q4What is the purpose of TCP congestion control?