Overview
TCP is reliable — it guarantees delivery, ordering, and error correction. UDP is unreliable — it does none of that. So why does UDP even exist? Because in certain situations, reliability is either not needed or comes at a cost that is too high. This tutorial walks through the concrete reasons you would choose UDP over TCP.
Key Terms
1. TCP vs UDP: A Quick Recap
| Feature | TCP | UDP |
|---|---|---|
| Reliability | ✅ Guaranteed delivery | ❌ Best-effort only |
| Connection | Connection-oriented (3-way handshake) | Connectionless |
| Ordering | ✅ Packets always in order | ❌ May arrive out of order |
| Overhead | Higher (handshake + teardown) | Lower (send and forget) |
| Speed | Slower for short exchanges | Faster for short exchanges |
| Broadcast/Multicast | ❌ Not supported | ✅ Supported |
| Use case | File transfer, HTTP, SSH | DNS, video streaming, gaming |
2. Reason 1: No Connection Overhead for Single Messages
TCP requires a 3-way handshake to set up a connection and a 4-way handshake to tear it down. For a single short request-response, this is wasteful.
A UDP server can receive requests from multiple clients and reply to them without setting up any connection. This makes UDP ideal when you are sending a single short message and expecting a single short reply.
3. Reason 2: Lower Latency for Request-Response
For a single request-response exchange, the best-case timing is:
Where:
- RTT = Round-Trip Time — time for a packet to go from client to server and back
- SPT = Server Processing Time — time the server takes to compute the response
UDP saves exactly one full RTT per request-response exchange. On intercontinental links where RTT can be 200–500 ms, this matters a lot.
Real Example: DNS
DNS uses UDP for exactly this reason. When your browser looks up google.com, it sends a single UDP packet to a DNS server and gets a single UDP packet back. No handshake, no teardown. The entire lookup can complete in one round trip.
/* Conceptual: What DNS does with UDP */
/* Client side */
sendto(udp_sock, dns_query, query_len, 0,
(struct sockaddr *)&dns_server, sizeof(dns_server));
recvfrom(udp_sock, dns_response, sizeof(dns_response), 0,
(struct sockaddr *)&server_addr, &addrlen);
/* No connect(), no close(), no handshake.
Single packet each way. Done. */
4. Reason 3: Broadcast and Multicast Support
TCP is a point-to-point protocol — it connects exactly two endpoints. UDP supports both broadcast and multicast:
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
/* Example: sending a UDP broadcast */
int send_broadcast(void)
{
int sock;
struct sockaddr_in dest;
int broadcastEnable = 1;
const char *msg = "Hello everyone on this network!";
sock = socket(AF_INET, SOCK_DGRAM, 0);
/* Must enable broadcast permission on the socket */
setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
&broadcastEnable, sizeof(broadcastEnable));
memset(&dest, 0, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(9999);
dest.sin_addr.s_addr = htonl(INADDR_BROADCAST); /* 255.255.255.255 */
sendto(sock, msg, strlen(msg), 0,
(struct sockaddr *)&dest, sizeof(dest));
/* TCP cannot do this at all */
return 0;
}
5. Reason 4: Streaming Media Does Not Need Reliability
For applications like video calls, audio streaming, or live gaming, the requirements are completely different from file transfer:
The key insight: TCP’s retransmission introduces unpredictable delay. For real-time media, a short gap in the stream is acceptable. An unexpected 500 ms freeze while TCP waits for a retransmit is not.
Applications like WebRTC, VoIP, and online games use UDP and implement their own lightweight recovery strategies at the application level — sequence numbers to detect loss, but no blocking retransmit.
6. When NOT to Use UDP
Protocols like QUIC (used by HTTP/3) are built on UDP but implement their own congestion control, reliability, and multiplexing. These are multi-year engineering efforts by large teams. Do not attempt this for a typical application.
Decision Guide
Need guaranteed delivery? → TCP
Single short request-response (like DNS)? → UDP
Real-time media (video/audio/gaming)? → UDP
One sender, many receivers (broadcast/multicast)? → UDP
Large file transfer? → TCP
Need reliability but want UDP? → Just use TCP instead
7. Code: Simple UDP Echo Server vs TCP Echo Server
UDP Echo Server (simpler, no connection management)
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#define PORT 9000
#define BUFSIZE 1024
int main(void)
{
int sock;
struct sockaddr_in server_addr, client_addr;
socklen_t client_len = sizeof(client_addr);
char buf[BUFSIZE];
ssize_t n;
sock = socket(AF_INET, SOCK_DGRAM, 0); /* UDP socket */
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;
bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
printf("UDP echo server waiting on port %d\n", PORT);
/*
* No listen(), no accept(), no connection tracking.
* One loop can serve requests from MANY different clients.
*/
for (;;) {
n = recvfrom(sock, buf, BUFSIZE, 0,
(struct sockaddr *)&client_addr, &client_len);
if (n < 0) { perror("recvfrom"); continue; }
/* Echo back to the same client */
sendto(sock, buf, n, 0,
(struct sockaddr *)&client_addr, client_len);
}
return 0;
}
/*
* TCP echo server for comparison:
* - Needs accept() loop
* - Needs separate handling per client (fork/thread/select)
* - More complex state management
* - But: reliable, ordered, stream-based
*/
Interview Questions
Reliability has a cost: connection setup, acknowledgement traffic, retransmissions, and head-of-line blocking. For short request-response exchanges (like DNS), real-time media streaming (video/audio calls), or broadcast/multicast scenarios, this cost outweighs the benefit. UDP skips all of this and simply sends the data, making it faster and simpler in these specific cases.
For a single request-response, TCP takes at minimum 2 × RTT + SPT: one RTT for the 3-way handshake and one RTT for the actual request and response, plus server processing time. UDP takes RTT + SPT: just one RTT for the request and response with no setup cost. This saves one full RTT, which matters on high-latency networks.
A DNS lookup is a single short question and a single short answer. Using UDP means it can be completed with one packet in each direction. TCP would require a 3-way handshake before the query, then a teardown after, adding significant latency for a tiny payload. DNS uses TCP only when a response is too large to fit in a single UDP datagram (over 512 bytes traditionally, or 4096 bytes with EDNS).
These applications are latency-sensitive, not loss-sensitive. If a TCP segment is lost, the receiver must wait for retransmission before any subsequent data can be delivered (head-of-line blocking). This causes the stream to pause unpredictably. With UDP, a lost packet is simply skipped — the stream continues with the next frame or audio sample, which produces a brief glitch but not a freeze. A short glitch is far less noticeable than a pause.
Broadcast sends a datagram to all hosts on a network (typically the local subnet). Every host receives it whether they want it or not. Multicast sends to a specific group identified by a multicast group address — only hosts that have explicitly joined that group receive the datagrams. Multicast is more efficient for targeted group communication across routers; broadcast is limited to a single subnet.
Implementing reliability on top of UDP (sequence numbers, ACKs, retransmission, duplicate detection, congestion control) is extremely complex. The resulting system is unlikely to outperform TCP, which is already a mature, well-tuned implementation of exactly these features. In most cases, the answer is: just use TCP instead. Only specialized high-performance protocols like QUIC (built by Google/IETF) invest the enormous effort to build reliable transport on UDP.
