UDP & DatagramSocket
UDP & DatagramSocket
User Datagram Protocol (UDP) is the second major transport-layer protocol alongside TCP. Where TCP gives you a reliable, ordered, connection-oriented byte stream, UDP gives you fast, connectionless, best-effort datagrams. Understanding both — and knowing when each is the right tool — is essential for any experienced Java developer building networked systems.
What UDP Actually Is
UDP sends individual datagrams: self-contained packets that carry a destination address, a source port, a destination port, a checksum, and a payload. Each datagram is routed independently. The protocol makes no guarantee that a packet arrives, arrives only once, or arrives in order. There is no handshake, no connection state, and no retransmission.
When to Choose UDP Over TCP
UDP is the right choice when speed and low latency matter more than reliability, or when the application can handle lost or reordered packets better than the operating system can. Classic use cases include:
- Real-time audio and video (VoIP, video conferencing, live streaming) — a slightly degraded frame is better than a stalled stream waiting for retransmission.
- Online multiplayer games — the position update from 50 ms ago is useless; send a fresh one instead of retransmitting the old one.
- DNS — queries and responses fit in a single packet; the client simply retries if no reply arrives.
- DHCP, SNMP, TFTP, NTP — protocols that are simple enough to manage their own reliability, or where low overhead outweighs occasional loss.
- Metrics and telemetry — losing a counter snapshot occasionally is acceptable; saturating the network with TCP overhead is not.
- Broadcast and multicast — UDP supports sending a single datagram to many recipients; TCP is point-to-point only.
Java's DatagramSocket and DatagramPacket
Java exposes UDP through two classes in java.net:
DatagramSocket— the socket that sends and receives datagrams. Bind it to a local port to receive; leave it unbound (or let the OS assign a port) to send-only.DatagramPacket— a container for one datagram: byte array, offset, length, and optionally anInetAddressand port (for outbound packets).
Building a UDP Echo Server
The server binds to a port, loops receiving packets, and echoes each one back to the sender's address and port — which UDP provides automatically in the received packet.
socket.receive(packet) the packet's length is set to the number of bytes actually received, which may be smaller than the buffer. If you re-use the same DatagramPacket for the next receive call without resetting its length to the full buffer size, receive() will only read into that smaller slice and silently truncate larger packets. Call packet.setLength(buffer.length) at the start of each loop iteration.
Building a UDP Client
The client creates an unbound socket (the OS assigns an ephemeral source port), sends a datagram to the server's address and port, then receives the echo.
Handling Packet Loss in Application Code
Because UDP provides no retransmission, any reliability the application needs must be implemented above the protocol. The standard pattern is send with timeout and retry:
Broadcast and Multicast
UDP supports two forms of one-to-many delivery that TCP cannot provide. Broadcast sends a datagram to every host on a subnet. Multicast sends to a group identified by a class-D IP address (224.0.0.0 – 239.255.255.255); only hosts that have joined the group receive the packets.
For multicast, use MulticastSocket (a subclass of DatagramSocket) and call joinGroup() on receivers:
Key Trade-offs to Remember
- No ordering guarantee — packets can arrive out of sequence. If order matters, add sequence numbers in your payload and sort at the receiver.
- No delivery guarantee — implement retransmission or accept loss, depending on the use case.
- No flow control or congestion control — a fast sender can overwhelm a slow receiver or a narrow link. You are responsible for rate-limiting.
- Maximum datagram size — the UDP payload limit is 65,507 bytes (65,535 minus IP and UDP headers). For reliable large-data transfer, fragment at the application layer or use TCP.
- Thread safety —
DatagramSocketis not thread-safe. Use one socket per thread, or synchronize explicitly.
java.nio.channels.DatagramChannel lets you use non-blocking I/O and a selector, multiplexing thousands of peers on a single thread — the same approach that powers high-performance game servers and streaming infrastructure.
Summary
UDP trades reliability for speed. Java's DatagramSocket and DatagramPacket give direct, low-overhead access to this protocol. Use UDP when latency matters more than guaranteed delivery, when the payload fits in one packet, or when broadcast and multicast are required. Implement any necessary reliability — retransmission, ordering, deduplication — in your application layer, and set a SO_TIMEOUT on every receive call to prevent indefinite blocking.