TCP vs. UDP socket latency benchmark
python, sockets, tcp, udp
Solution
Your TCP socket is connected but your UDP socket is not. This means extra processing for every send/receive on the UDP socket. Call `connect` on each side for the UDP socket, just like you call `connect`/`accept` on the TCP socket.
Programs like `iperf` do this to measure accurately.
Problem
I have implemented a small benchmark for socket communication via TCP and UDP in Python. Surprisingly, TCP is almost exactly double as fast as UDP. To avoid routing effects, server and client are running on the same Unix machine, but on different threads. Maybe the code is useful. Here is the server code: ``` import socket import sys host = 'localhost' port = 8888 buffersize = 8 server_address = (host, port) def start_UDP_server(): socket_UDP = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) socket_UDP.bind(server_address) print("UDP server is running...") while True: data, from_address = socket_UDP.recvfrom(buffersize) if not data: break socket_UDP.sendto(data, from_address) socket_UDP.close() def start_TCP_server(): socket_TCP = socket.socket(socket.AF_INET, socket.SOCK_STREAM) socket_TCP.bind(server_address) socket_TCP.listen(1) print("TCP server is running...") while True: client, client_address = socket_TCP.accept() while True: data = client.recv(buffersize) if not data: break client.sendall(data) client.close() ``` So you can run either `start_TCP_server()` or `start_UDP_server()`. On client side the code is: ``` import socket import sys import time host = 'localhost' port = 8888 buffersize = 8 server_address = (host, port) client_address = (host, port+1) N = 1000000 def benchmark_UDP(): socket_UDP = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) socket_UDP.bind(client_address) print("Benchmark UDP...") duration = 0.0 for i in range(0, N): b = bytes("a"*buffersize, "utf-8") start = time.time() socket_UDP.sendto(b, server_address) data, from_address = socket_UDP.recvfrom(buffersize) duration += time.time() - start if data != b: print("Error: Sent and received data are bot the same") print(duration*pow(10, 6)/N, "µs for UDP") def benchmark_TCP(): socket_TCP = socket.socket(socket.AF_INET, socket.SOCK_STREAM) socket_TCP.connect(server_address) print("Benchmark TCP...") duration = 0.0 for i in range(0, N): b = bytes("a"*buffersize, "utf-8") start = time.time() socket_TCP.sendall(b) data = socket_TCP.recv(buffersize) duration += time.time() - start if data != b: print("Error: Sent and received data are bot the same") print(duration*pow(10, 6)/N, "µs for TCP") socket_TCP.close() ``` Like for the server you can start the benchmark by `benchmark_TCP()` or `benchmark_UDP()`. The results are about 25 µs for TCP, and about 54 µs for UDP on Unix and even worse for Windows (about 30 µs for TCP and more than 200 µs for UDP). Why? I would expect a minimal advantage for UDP.