How to Write a Simple UDP Echo Server
A User Datagram Protocol (UDP) echo server is a network application
that listens for incoming datagrams and sends the exact same data back
to the sender. This article explains how a UDP echo server works,
provides a complete implementation in Python using the standard
socket library, demonstrates a simple client for testing,
and covers the core mechanics of connectionless socket programming.
Understanding the UDP Echo Model
Unlike TCP, UDP is a connectionless transport protocol. It does not establish a handshake, manage persistent connections, or guarantee packet delivery.
A UDP echo server operates using a continuous loop with four core
steps: 1. Create a socket configured for UDP (SOCK_DGRAM).
2. Bind the socket to a specific IP address and port. 3. Wait to receive
a datagram along with the sender’s network address using
recvfrom(). 4. Transmit the received data directly back to
the sender’s address using sendto().
Python UDP Echo Server Implementation
Python’s built-in socket module provides direct access
to operating system networking primitives. Below is the complete server
code:
import socket
def run_udp_server(host="127.0.0.1", port=9999):
# 1. Create a UDP socket (AF_INET for IPv4, SOCK_DGRAM for UDP)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 2. Bind the socket to the host address and port
server_socket.bind((host, port))
print(f"UDP Echo Server listening on {host}:{port}")
try:
while True:
# 3. Receive data and client address (buffer size 1024 bytes)
data, client_address = server_socket.recvfrom(1024)
print(f"Received {len(data)} bytes from {client_address}: {data.decode('utf-8', errors='replace')}")
# 4. Echo the received data back to the sender
server_socket.sendto(data, client_address)
except KeyboardInterrupt:
print("\nServer shutting down.")
finally:
server_socket.close()
if __name__ == "__main__":
run_udp_server()Testing with a UDP Echo Client
To test the server, create a client script that sends a message and listens for the echoed response:
import socket
def run_udp_client(host="127.0.0.1", port=9999, message="Hello, UDP Server!"):
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client_socket.settimeout(2.0) # Set a timeout for response
try:
# Send message
client_socket.sendto(message.encode("utf-8"), (host, port))
print(f"Sent: {message}")
# Wait for echo response
response, _ = client_socket.recvfrom(1024)
print(f"Echo received: {response.decode('utf-8')}")
except socket.timeout:
print("Request timed out. No response from server.")
finally:
client_socket.close()
if __name__ == "__main__":
run_udp_client()Key Technical Considerations
- No
listen()oraccept(): TCP servers requirelisten()to queue connections andaccept()to establish communication channels. UDP skips these steps because it processes individual packets rather than continuous streams. - Buffer Size: The
recvfrom(1024)method sets the maximum packet payload size to read at once. If an incoming datagram exceeds this buffer, truncation or packet loss may occur depending on the operating system. - Statelessness: The server does not track client states. Every incoming packet is treated as an independent event containing both the payload and the origin address.