- Send and receive UDP datagrams
- Build UDP client-server applications
- Understand broadcast and multicast
- Handle packet loss in UDP applications
UDP and Datagram Sockets
UDP prioritizes speed over reliability. Connectionless, no delivery guarantees, no order. Perfect for real-time apps where speed beats accuracy—streaming, gaming, DNS.
TCP vs UDP Comparison
| Feature | TCP | UDP |
|---|---|---|
| Connection | Required | None |
| Reliability | Guaranteed | Best-effort |
| Order | Maintained | Not maintained |
| Speed | Slower | Faster |
| Overhead | Higher | Lower |
| Use Cases | HTTP, Email, FTP | Streaming, DNS, Gaming |
UDP Basics
UDP works with datagrams (packets):
import java.net.DatagramSocket;
import java.net.DatagramPacket;
import java.net.InetAddress;
// Key classes:
// DatagramSocket - endpoint for UDP communication
// DatagramPacket - container for data being sent/received
Sending UDP Packets
Simple Sender
public class UDPSender {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket();
String message = "Hello, UDP!";
byte[] data = message.getBytes();
InetAddress address = InetAddress.getByName("localhost");
int port = 9999;
DatagramPacket packet = new DatagramPacket(
data, // byte array
data.length, // data length
address, // destination address
port // destination port
);
socket.send(packet);
System.out.println("Sent: " + message);
socket.close();
}
}
Sending Multiple Messages
public class UDPClient {
public static void main(String[] args) throws Exception {
try (DatagramSocket socket = new DatagramSocket()) {
InetAddress serverAddress = InetAddress.getByName("localhost");
int serverPort = 9999;
String[] messages = {"Hello", "How are you?", "Goodbye"};
for (String msg : messages) {
byte[] data = msg.getBytes();
DatagramPacket packet = new DatagramPacket(
data, data.length, serverAddress, serverPort);
socket.send(packet);
System.out.println("Sent: " + msg);
Thread.sleep(500); // Wait a bit between messages
}
}
}
}
Receiving UDP Packets
Simple Receiver
public class UDPReceiver {
public static void main(String[] args) throws Exception {
int port = 9999;
try (DatagramSocket socket = new DatagramSocket(port)) {
System.out.println("UDP server listening on port " + port);
byte[] buffer = new byte[1024];
while (true) {
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet); // Blocks until packet received
// Extract data
String message = new String(
packet.getData(),
0,
packet.getLength()
);
// Get sender info
InetAddress senderAddress = packet.getAddress();
int senderPort = packet.getPort();
System.out.println("Received from " + senderAddress + ":" + senderPort
+ " -> " + message);
}
}
}
}
UDP Echo Server
A server that echoes back what it receives:
public class UDPEchoServer {
public static void main(String[] args) throws Exception {
int port = 9999;
try (DatagramSocket socket = new DatagramSocket(port)) {
System.out.println("Echo server started on port " + port);
byte[] buffer = new byte[1024];
while (true) {
// Receive packet
DatagramPacket receivePacket = new DatagramPacket(buffer, buffer.length);
socket.receive(receivePacket);
String received = new String(
receivePacket.getData(), 0, receivePacket.getLength());
System.out.println("Received: " + received);
// Echo back
String response = "Echo: " + received;
byte[] responseData = response.getBytes();
DatagramPacket sendPacket = new DatagramPacket(
responseData,
responseData.length,
receivePacket.getAddress(), // Send back to sender
receivePacket.getPort()
);
socket.send(sendPacket);
}
}
}
}
UDP Client with Response
public class UDPClientWithResponse {
public static void main(String[] args) throws Exception {
try (DatagramSocket socket = new DatagramSocket()) {
// Set timeout for receive
socket.setSoTimeout(5000);
// Send message
String message = "Hello, Server!";
byte[] sendData = message.getBytes();
InetAddress serverAddress = InetAddress.getByName("localhost");
DatagramPacket sendPacket = new DatagramPacket(
sendData, sendData.length, serverAddress, 9999);
socket.send(sendPacket);
System.out.println("Sent: " + message);
// Receive response
byte[] receiveBuffer = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(
receiveBuffer, receiveBuffer.length);
try {
socket.receive(receivePacket);
String response = new String(
receivePacket.getData(), 0, receivePacket.getLength());
System.out.println("Response: " + response);
} catch (SocketTimeoutException e) {
System.err.println("No response received (timeout)");
}
}
}
}
Broadcasting
UDP supports broadcasting to all hosts on a network:
public class UDPBroadcaster {
public static void main(String[] args) throws Exception {
try (DatagramSocket socket = new DatagramSocket()) {
socket.setBroadcast(true); // Enable broadcasting
String message = "Broadcast message!";
byte[] data = message.getBytes();
// Broadcast address (all hosts on local network)
InetAddress broadcastAddress = InetAddress.getByName("255.255.255.255");
DatagramPacket packet = new DatagramPacket(
data, data.length, broadcastAddress, 9999);
socket.send(packet);
System.out.println("Broadcast sent!");
}
}
}
Multicast
Send to a group of hosts:
import java.net.MulticastSocket;
public class MulticastSender {
public static void main(String[] args) throws Exception {
InetAddress group = InetAddress.getByName("230.0.0.1"); // Multicast address
int port = 8888;
try (MulticastSocket socket = new MulticastSocket()) {
String message = "Hello, multicast group!";
byte[] data = message.getBytes();
DatagramPacket packet = new DatagramPacket(
data, data.length, group, port);
socket.send(packet);
System.out.println("Multicast message sent!");
}
}
}
public class MulticastReceiver {
public static void main(String[] args) throws Exception {
InetAddress group = InetAddress.getByName("230.0.0.1");
int port = 8888;
try (MulticastSocket socket = new MulticastSocket(port)) {
socket.joinGroup(group);
System.out.println("Joined multicast group");
byte[] buffer = new byte[1024];
while (true) {
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
String message = new String(
packet.getData(), 0, packet.getLength());
System.out.println("Received: " + message);
}
// socket.leaveGroup(group); // When done
}
}
}
Handling Large Data
UDP packets have size limits (typically 65,507 bytes max):
public class LargeDataSender {
private static final int MAX_PACKET_SIZE = 8192; // Safe size
public static void sendLargeData(DatagramSocket socket,
byte[] data, InetAddress address, int port) throws Exception {
int offset = 0;
int sequenceNumber = 0;
while (offset < data.length) {
int length = Math.min(MAX_PACKET_SIZE - 4, data.length - offset);
// Create packet with sequence number
byte[] packetData = new byte[length + 4];
// Add sequence number (first 4 bytes)
packetData[0] = (byte) (sequenceNumber >> 24);
packetData[1] = (byte) (sequenceNumber >> 16);
packetData[2] = (byte) (sequenceNumber >> 8);
packetData[3] = (byte) sequenceNumber;
// Copy data
System.arraycopy(data, offset, packetData, 4, length);
DatagramPacket packet = new DatagramPacket(
packetData, packetData.length, address, port);
socket.send(packet);
offset += length;
sequenceNumber++;
}
}
}
Best Practices
- Handle packet loss - UDP doesn't guarantee delivery
- Set timeouts - Don't wait forever for responses
- Limit packet size - Stay within network MTU (usually ~1500 bytes)
- Add sequence numbers - For ordered processing if needed
- Implement acknowledgments - For reliability if needed
- Use appropriate buffer sizes
// Good UDP practices
DatagramSocket socket = new DatagramSocket();
socket.setSoTimeout(5000); // 5 second timeout
socket.setReceiveBufferSize(65536); // Larger buffer
// Check for errors before processing
if (packet.getLength() > 0) {
processPacket(packet);
}
When to Use UDP
Use UDP when:
- Speed is more important than reliability (gaming, streaming)
- You're building your own reliability layer
- Broadcasting/multicasting is needed
- Small, independent messages (DNS queries)
- Real-time data where old data is useless
Use TCP when:
- Reliability is required (file transfer, email)
- Order matters (protocols, transactions)
- Large data transfers
- You don't want to implement reliability yourself
UDP is fast but unreliable. DatagramSocket and DatagramPacket handle sending/receiving. No connection setup. Handle packet loss in your app. Set timeouts to avoid blocking. MulticastSocket for group communication. Good for real-time apps where speed beats reliability—gaming, streaming, DNS.
