UDP Protocol
UDP Protocol
Definition: User Datagram Protocol (UDP) is a lightweight, connectionless transport protocol that sends independent datagrams to a destination IP:port without establishing a connection, tracking state, or guaranteeing delivery.
How It Works
There’s no handshake. An application calls sendto() with a destination address and the data goes out as a single UDP datagram immediately, wrapped directly in an IP packet. There’s no concept of a “connection” at the protocol level, each datagram is entirely independent; two datagrams from the same sender to the same destination have no relationship to each other as far as UDP is concerned.
The receiver gets datagrams via recvfrom(), which also returns the sender’s address, since there’s no prior connect() establishing who’s on the other end. If a datagram is lost in transit, dropped by a congested router, corrupted, arrives out of order, or duplicated, UDP does nothing about it. No retransmission, no reordering, no deduplication. Any of that, if needed, is the application’s job.
Under the Hood
UDP header, just 8 bytes:
| Field | Size | Purpose |
|---|---|---|
| Source port | 2 bytes | Sender’s port (can be 0 if no reply expected) |
| Destination port | 2 bytes | Receiver’s port |
| Length | 2 bytes | Total length of header + data |
| Checksum | 2 bytes | Optional in IPv4, mandatory in IPv6 |
Compare that to TCP’s 20+ byte header carrying sequence numbers, ACK numbers, window size, and flags, UDP simply doesn’t have the fields needed to track state, by design.
A worked example, a DNS query from port 52341 to port 53 with a 29-byte payload, hex-dumped:
CC 75 00 35 00 25 8A 1F [payload...]
Breaking that down: CC 75 = 52341 (source port), 00 35 = 53 (destination port), 00 25 = 37 (length, 8-byte header + 29-byte payload), 8A 1F = checksum. There’s no sequence number, no flags, no window, the entire header fits in the first 8 bytes and the rest is immediately payload.
Because UDP has no flow or congestion control, applications that need to be network-friendly (video streaming, WebRTC) implement their own congestion-aware logic on top, or risk starving other traffic sharing the link. This absence is also why UDP is the vector of choice for amplification DDoS attacks: since UDP requires no handshake, an attacker can spoof a victim’s source IP and send a small request to a service (DNS, NTP, memcached) that responds with a much larger reply, aimed entirely at the spoofed victim, with the protocol offering no mechanism to verify the source address was real.
QUIC (the transport underlying HTTP/3) is built on top of UDP specifically to get around kernel- and middlebox-level ossification around TCP, and reimplements reliability, ordering, and congestion control itself, but per-stream rather than globally, so one lost packet only blocks the stream it belongs to, not every other in-flight stream on the connection (avoiding TCP’s head-of-line blocking).
UDP checksum being optional in IPv4 (a value of all-zero bits means “no checksum used”) reflects its original design philosophy: minimize overhead and let applications that care about integrity handle it themselves, e.g. via RTP sequence numbers plus application-level error concealment for lost video frames. IPv6 mandates the checksum because IPv6 removed the IP-layer header checksum that IPv4 had.
When to Choose UDP Over TCP
- Latency-critical, loss-tolerant data: live video/audio, where a stale retransmitted frame is worse than just dropping it and moving on.
- Simple request/response with small payloads: DNS queries avoid the cost of a full TCP handshake for a single small exchange.
- Custom reliability semantics: applications like online games often need partial reliability (guarantee some messages, not others) or want to prioritize freshness over completeness, easier to build from scratch on UDP than to fight TCP’s strict ordering.
- Multicast/broadcast delivery: TCP is inherently one-to-one; UDP-based protocols can address multiple receivers at once (used in some streaming and discovery protocols).
- Building a new transport protocol: QUIC, SCTP-over-UDP, and similar modern designs use UDP as a substrate specifically because it’s simple and unencumbered, letting them implement exactly the reliability and congestion behavior they want rather than inheriting TCP’s.
History
UDP was standardized in RFC 768 (1980), written by Jon Postel in a single short document, deliberately minimal, essentially “IP plus port numbers,” in contrast to the much larger TCP specification being developed in parallel. For decades it was treated mainly as the protocol for DNS, simple network services, and (starting in the 1990s and 2000s) real-time media, while TCP handled essentially all “serious” application traffic.
That balance shifted with the rise of QUIC, developed at Google starting around 2012 and standardized as RFC 9000 (2021), which deliberately builds on UDP specifically because TCP’s behavior is baked so deeply into OS kernels and middleboxes (routers, load balancers, corporate firewalls) that evolving TCP itself at internet scale had become impractically slow. HTTP/3, standardized in 2022, runs over QUIC/UDP rather than TCP, marking the first time a huge share of ordinary web traffic moved off TCP since the web began.
Why It Matters
For real-time applications, a slightly corrupted or dropped video frame is a minor glitch; a TCP-style retransmission-and-wait for that same frame would stall everything after it and make the call visibly lag. UDP’s willingness to drop and move on, rather than guarantee delivery, is exactly what real-time and high-throughput, loss-tolerant use cases need. Its low overhead (no handshake, no per-connection state, tiny header) also makes it the natural choice for simple request/response protocols like DNS, where the cost of an occasional retried query is far lower than the cost of a TCP handshake for every single lookup.
Practical Reliability Patterns
Applications that need “some” reliability without full TCP semantics commonly build:
- Application-level ACKs: the receiver sends back a small confirmation datagram; the sender retransmits after a timeout if none arrives, used in lightweight custom protocols and game netcode.
- Sequence numbers without reordering guarantees: enough to detect and discard duplicates or stale/late packets (e.g. an older game-state update arriving after a newer one), without paying for full in-order delivery.
- Forward error correction (FEC): sending redundant data so the receiver can reconstruct a lost packet without asking for a retransmission at all, common in real-time video where a round trip to request a resend would already be too late.
- Periodic full-state resync: instead of guaranteeing every update arrives, periodically resend the full current state so a missed update self-corrects on the next cycle.
Common Pitfalls
- Assuming UDP is inherently unreliable and unusable for anything important, in practice DNS, DHCP, and QUIC/HTTP3 all run over UDP successfully by building exactly the reliability guarantees they need at the application layer, no more, no less.
- Building a “reliable” protocol over UDP naively (e.g. simple ACK-and-retry) without proper congestion control, this can be actively harmful to shared network links under load, unlike TCP which backs off automatically.
- UDP amplification/reflection attacks: because the source IP is trivially spoofable and there’s no handshake to prove the sender owns that address, UDP-based services (open DNS resolvers, NTP, memcached) are commonly abused to flood a third-party victim.
- Assuming an unanswered UDP
sendto()means failure, UDP has no delivery confirmation at all, silence could mean packet loss, a firewall drop, or simply that no response was expected. - Firewall/NAT traversal issues: UDP has no connection state for middleboxes to key off, so NAT mappings for UDP rely purely on idle timeouts, which can expire mid-session (e.g. in a long-idle VoIP call) and silently break the flow.
Comparison
| UDP | TCP | QUIC | |
|---|---|---|---|
| Connection setup | None | 3-way handshake | 0-1 RTT (includes TLS) |
| Reliability | None (app’s responsibility) | Guaranteed, ordered | Guaranteed per-stream |
| Header overhead | 8 bytes | 20+ bytes | Larger, but amortized with multiplexing |
| Head-of-line blocking | N/A | Yes | No, isolated per stream |
| Congestion control | None built in | Built in, mandatory | Built in, mandatory |
| Multicast support | Yes | No | No |
| Typical use | DNS, VoIP, gaming, streaming | Web (HTTP/1.1, 2), SSH, databases | HTTP/3 |
Debugging a UDP Issue
UDP’s lack of any handshake or error signaling makes failures quieter than TCP’s, diagnosis leans more heavily on packet capture:
tcpdump -i eth0 udp port 53(or the relevant port) shows whether a request is actually leaving the host at all, and whether any response comes back, unlike TCP there’s no[SYN]/[RST]to read, just presence or absence of datagrams.- A request going out with no reply, and no ICMP “port unreachable” message either, usually means the packet is being silently dropped by a firewall somewhere along the path, since UDP itself gives no feedback.
- An ICMP “destination unreachable, port unreachable” response arriving instead of application data means the target host is up but nothing is listening on that port, a clear signal to check the service’s status rather than the network path.
- For NAT/firewall-related drops mid-session (e.g. a VoIP call that cuts out after sitting idle), check whether the gap matches the NAT device’s idle timeout, a periodic keepalive datagram from the application is the standard fix.
nc -u -zv host portsends a UDP probe similar to a TCP port check, though because UDP has no handshake, a “success” fromnconly confirms the packet was sent, not that anything actually received or processed it.
Example
dig example.com performs a DNS lookup over a single UDP request/response pair (falling back to TCP only if the response is too large to fit in one UDP datagram). A packet capture of a video call shows a steady stream of UDP datagrams on ephemeral ports with no visible handshake, in contrast to the SYN/SYN-ACK/ACK preceding any TCP-based traffic in the same capture.
FAQ
Is UDP always faster than TCP? For a single small exchange, yes, no handshake overhead. For sustained bulk transfer, “faster” depends entirely on what the application builds on top, naive UDP with no congestion control can be faster right up until it causes packet loss and cross-traffic gets worse for everyone.
Does UDP have any concept of a “connection” at all? No at the protocol level, but connect() can still be called on a UDP socket, it just fixes a default destination address in the OS so subsequent send() calls don’t need to specify it each time, and lets the kernel deliver ICMP errors for that destination back to the socket.
Why do DNS responses sometimes switch to TCP? When a response exceeds what fits safely in a single UDP datagram (historically 512 bytes without EDNS0, larger with it), the server sets a flag telling the client to retry the query over TCP instead.
Can UDP packets arrive out of order? Yes, since each datagram routes independently through the network, and there’s nothing in UDP itself to reorder them at the receiver, that’s entirely on the application if it matters.