UDP Server (IPv4) - Timeout Mode
UDP = User Datagram Protocol
Solution
"""UDP Server (IPv4) - Timeout Mode
"""
from __future__ import annotations
import logging
import socket
import struct
from typing import Any
from net import handle_reuse_address, handle_reuse_port, handle_socket_bufsize
logging.basicConfig(
level=logging.DEBUG, style='{', format='[{processName} ({process})] {message}'
)
logger = logging.getLogger()
def recv_bin_data(sock: socket.socket, unpacker: struct.Struct):
data, client_address = sock.recvfrom(unpacker.size)
if data:
logger.debug(f'recv: {data!r}, from {client_address}')
unpacked_data: tuple[Any, ...] = unpacker.unpack(data)
logger.debug(f'recv unpacked: {unpacked_data}')
def run_server(
host: str = '',
port: int = 0,
*,
reuse_address: bool = False,
reuse_port: bool = True,
timeout: float | None = None,
recv_buf_size: int | None = None,
send_buf_size: int | None = None,
):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
handle_reuse_address(sock, reuse_address)
handle_reuse_port(sock, reuse_port)
# Bind
sock.bind((host, port))
server_address: tuple[str, int] = sock.getsockname()
logger.debug(f'Server address: {server_address}')
handle_socket_bufsize(sock, recv_buf_size, send_buf_size)
binary_fmt: str = '! I 2s Q 2h f'
unpacker = struct.Struct(binary_fmt)
# Accept and handle incoming client requests
try:
sock.settimeout(timeout)
logger.debug(f'Server recv/send timeout: {sock.gettimeout()} seconds')
while True:
data, client_address = sock.recvfrom(1024)
if data:
logger.debug(f'recv: {data!r}, from: {client_address}')
sock.sendto(data, client_address)
logger.debug(f'sent: {data!r}, to: {client_address}')
else:
logger.debug(f'no data from {client_address}')
break
recv_bin_data(sock, unpacker)
finally:
sock.close()
# host
# - 'localhost': socket.INADDR_LOOPBACK
# - '' or '0.0.0.0': socket.INADDR_ANY
# - socket.INADDR_BROADCAST
# Port 0 means to select an arbitrary unused port
run_server('localhost', 9999, timeout=5.0)
See source code
More
- TCP/UDP Reuse Address
- TCP/UDP Reuse Port
- TCP/UDP (Recv/Send) Buffer Size
- Pack/Unpack Binary Data:
struct
References
- Python -
socket
module - Python -
struct
module - PEP 3151 – Reworking the OS and IO exception hierarchy
- Linux Programmer’s Manual -
socket
(2) - Linux Programmer’s Manual -
bind
(2) - Linux Programmer’s Manual -
getsockname
(2) - Linux Programmer’s Manual -
recvfrom
(2) - Linux Programmer’s Manual -
sendto
(2) - Linux Programmer’s Manual - udp(7)