Concepts / Ports, sockets and UDP

Ports, sockets and UDP

UDP

Also called user datagram protocol, datagram

Independent datagrams with ports and nothing else: no connection, no acknowledgement, no retries.

A sender's success only means the datagram left. A closed port may answer with ICMP port unreachable. DNS, DHCP, VoIP and WireGuard use UDP: they prefer a small gap, or their own recovery, to TCP's waiting.

How UDP works, step by step

UDP (RFC 768) adds almost nothing to IP: ports, so a datagram reaches the right program, and a checksum. Its header is 8 bytes, four fields of 16 bits:

Field Meaning
Source port where replies should go; may be 0 if none are wanted
Destination port the program on the receiving machine: 53 for DNS, 67 and 68 for DHCP, 123 for NTP
Length header plus data, in bytes
Checksum covers header, data and a pseudo-header of the IP addresses; optional in IPv4, required in IPv6

Sending a DNS question shows the whole protocol:

  1. The program writes one message to a UDP socket. The kernel picks an ephemeral source port if the program did not bind one.
  2. The kernel wraps it in a UDP header and an IP packet and sends it. No handshake comes first.
  3. The receiving kernel checks the checksum, looks up a socket bound to the destination port and queues the datagram, whole, for that program. One write, one read: message boundaries survive, unlike TCP's byte stream.
  4. The program answers, to the source address and port it read.

Nothing else happens. No acknowledgement, no retransmission, no ordering, no rate control. If a datagram is lost, the program finds out only by not getting an answer, and decides itself whether to ask again: a DNS resolver retries after a timeout, a voice call plays a tiny gap and moves on.

A datagram to a port where nothing listens is answered by the receiving kernel with an ICMP port unreachable, unless a firewall drops it. The sender's program only learns of that if its socket is connected and it reads again.

What it looks like on a Linux machine

In the TCP and UDP lab the server runs an echo service on port 7, over TCP and UDP. ss shows the UDP socket as UNCONN, not LISTEN: there are no connections to accept, only datagrams to read.

$ ss -tulnp
Netid State  Recv-Q Send-Q Local Address:Port  Peer Address:Port Process
udp   UNCONN 0      0                  *:7                *:*    users:(("socat",pid=8,fd=5))
tcp   LISTEN 0      5                  *:7                *:*    users:(("socat",pid=7,fd=5))

The laptop sends hello by UDP, then to port 9, where nothing listens:

$ tcpdump -nn -i eth0 udp or icmp
IP 10.0.1.10.48438 > 10.0.2.10.7: UDP, length 6
IP 10.0.2.10.7 > 10.0.1.10.48438: UDP, length 6
IP 10.0.1.10.52001 > 10.0.2.10.9: UDP, length 6
IP 10.0.2.10 > 10.0.1.10: ICMP 10.0.2.10 udp port 9 unreachable, length 42

Two packets for the echo, where TCP needed ten. And nc -u exits with 0 for port 9 too: sending worked, and that is all UDP ever promised.

TCP vs UDP

UDP TCP
Setup None Three-way handshake
Reliability None; the program retries if it cares Acknowledgements and retransmission
Order Not kept Kept
Message boundaries Kept: one send, one datagram Lost: a stream of bytes
Header 8 bytes 20 to 60 bytes
One to many Broadcast and multicast work One peer per connection
Typical uses DNS, DHCP, NTP, SNMP, VoIP, games, QUIC Web, SSH, mail, databases

UDP is the right choice when a late answer is worthless, when one packet is the whole conversation, or when the program builds its own reliability, as QUIC does for HTTP/3.

What goes wrong, and how you see it

Silence. A UDP scan cannot tell an open port that does not reply from a firewall that drops: both look the same. Only an ICMP port unreachable proves a port closed. Loss under load. A receiver too slow to read lets its socket buffer fill, and the kernel drops what arrives: netstat -su counts receive buffer errors. Big datagrams. Anything larger than the path MTU is fragmented, and losing one fragment loses the whole datagram; that is why DNS software now offers 1232 bytes over UDP and moves larger answers to TCP. Spoofing. No handshake means the source address is not checked, which is what DNS amplification exploits.

Questions people ask

Why use UDP if it is unreliable? Because waiting is worse for some traffic. A resent voice packet arrives too late to play, and a one-packet DNS question is cheaper to repeat than to open a connection for.

Is UDP connectionless? Yes. A program may connect() a UDP socket, but that only fixes the peer address in the kernel; nothing is sent.

Does UDP have flow control? No. Protocols built on it, such as QUIC, add their own.

See it on real machines

Learn it on real machines.

Every lab is a small network of real Linux machines in your browser. Start with a free account: Google or email, no card.

Start this lab, free