IP moves packets between machines, but it promises nothing: packets can be lost, duplicated or arrive out of order. The transport layer sits on top and decides what to do about that.
TCP: reliable and in order
TCP gives your program a reliable stream of bytes:
- Connection first: a quick handshake (SYN, SYN-ACK, ACK) before any data. That's one round trip of waiting.
- Every byte arrives: the receiver acknowledges what it got, and the sender re-sends anything lost.
- In order: if packet 5 is missing, packets 6, 7 and 8 wait until 5 arrives. This is called head-of-line blocking.
- Polite: it slows down when the network is congested.
Most web traffic, APIs, databases, file transfers and email use TCP, because a missing byte would corrupt the data.
UDP: fast and fire-and-forget
UDP just sends independent packets (datagrams). No handshake, no acknowledgements, no re-sending, no ordering. If a packet is lost, it's gone, unless the application handles it.
That sounds worse, but for live data it's often better. In a video call or an online game, a packet that arrives late is useless: by then you need the next frame. Waiting for a re-send would freeze everything. Better to skip it and carry on.
UDP is used for voice and video calls, live streaming, online games, and DNS lookups (one small question, one small answer; just ask again if it's lost).
Choosing
| Need | Choose |
|---|---|
| Every byte must arrive, in order | TCP |
| Fresh data matters more than complete data | UDP |
| Tiny request and answer, easy to retry | UDP is fine |
A modern twist: QUIC, the protocol under HTTP/3, runs on UDP but adds its own reliability per stream. So one lost packet only stalls the stream it belongs to, not the whole connection.
Key idea: TCP trades a little speed for reliability and order. UDP trades reliability for speed and freshness. Pick based on whether a late packet is still useful.