When running a simple UDP listener with:
nc -l -u -p 1234
You'll notice it terminates after receiving the first packet. Subsequent sends result in "Connection refused" errors. This happens because:
- Netcat's default UDP mode isn't truly connectionless - it tries to maintain pseudo-connections
- The original implementation closes the socket after first receive
Method 1: Using GNU Netcat's -k flag
nc -l -u -p 1234 -k
The -k (keep-open) flag works in GNU netcat variants to maintain the listening socket.
Method 2: Ncat (Modern alternative)
ncat -l -u -p 1234 --keep-open
Method 3: Continuous Loop (POSIX shell)
while true; do
nc -l -u -p 1234
done
For proper UDP service implementation, consider these robust approaches:
# Using socat for persistent UDP service
socat UDP-RECV:1234,fork -
Or with timestamp logging:
socat -u UDP-RECV:1234,fork \
EXEC:'date +%s; cat'
- Add proper error handling and logging
- Consider packet size limitations (use -s or buffer controls)
- For high traffic, implement rate limiting
- Use timeouts (-w flag) where appropriate
Verify with continuous sending:
for i in {1..10}; do
echo "Packet $i" | nc -u localhost 1234
sleep 1
done
When running a simple UDP listener with netcat:
nc -l -u -p 1234
You'll notice it only processes the first incoming packet before terminating. Subsequent packets result in "Connection refused" errors:
$ echo "test1" | nc -u localhost 1234 # Works
$ echo "test2" | nc -u localhost 1234 # Fails with "read(net): Connection refused"
Netcat's default UDP implementation treats each packet as a complete transaction. Unlike TCP, UDP is connectionless, so the traditional netcat implementation doesn't maintain state between packets.
Here are three reliable approaches to handle multiple UDP packets:
1. Using Netcat in a Loop
The simplest cross-platform solution:
while true; do
nc -l -u -p 1234
done
2. Using Socat (Superior Alternative)
Socat provides better UDP handling:
socat UDP-RECV:1234 -
For verbose output with timestamps:
socat -v UDP-RECV:1234 -
3. Python Persistent UDP Server
For more control, use this Python script (save as udp_server.py):
import socket
UDP_IP = "0.0.0.0"
UDP_PORT = 1234
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))
while True:
data, addr = sock.recvfrom(1024)
print(f"Received: {data.decode()} from {addr}")
Run with: python3 udp_server.py
Send test packets with netcat:
for i in {1..5}; do echo "Packet $i" | nc -u localhost 1234; done
Or with Python:
import socket
UDP_IP = "127.0.0.1"
UDP_PORT = 1234
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for i in range(5):
sock.sendto(f"Python packet {i}".encode(), (UDP_IP, UDP_PORT))
For continuous data streams (like logs), modify the Python server:
import socket
from datetime import datetime
UDP_IP = "0.0.0.0"
UDP_PORT = 1234
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))
print(f"UDP server started at {datetime.now()}")
try:
while True:
data, addr = sock.recvfrom(65535) # Max UDP packet size
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
print(f"[{timestamp}] {addr[0]}:{addr[1]} - {data.decode()}")
except KeyboardInterrupt:
print("\nServer terminated")
finally:
sock.close()