Using SO_REUSEPORT Flag In Multi-Processes UDP Server

SO_REUSEPORT is a new flag available in Linux 3.9+ that allows several threads to bind the same port simultaneously instead of having to race for the same socket, having the kernel round-robin between them. And this was intended to improve the performance of multi-threaded network server applications running on top of multi-core systems.

The real application of this feature should be when sometimes a worker is stalled by a blocking operation, which does not only affect connections that the worker has already accepted, but also connection requests that the kernel has assigned to the worker since it became blocked.

SO_REUSEPORT

In case of using SO_REUSEPORT the kernel will have multiple Socket Listeners. This will increase the throughput of the application and ensure that blocking operations are not affecting other workers.

SO_REUSEPORT_ENABLED

Typical UDP Server

It binds to a specific port and iterates every portion of to read data from the socket.

import socket

def worker(data):
    # do some magic with data
    print 'received %r' %data
port = 5050
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("", port))

print "waiting on port:%s \n" %(port)
while 1:
    data, addr = s.recvfrom(1024)
    worker(data)

Multi-threaded UDP Server

import threading
import socket

def worker(data):
    # do some magic with data
    return True
 
port = 5050 
def open_socket(tnum):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
    s.bind(("", port)) 
    while 1:
        data, addr = s.recvfrom(1024)
        print "thread %r recieved %r" %(tnum,data)

threads=[]
for i in range(0,100):
    t = threading.Thread(target=open_socket,args=(i,))
    threads.append(t)
    t.start()

Multi-Processes UDP Server

import threading
import socket
import os
port = 5050 

def worker(data):
    # do some magic with data
    return True

def open_socket(tnum): 
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) 
    s.bind(("", port)) 
    while 1: 
        data, addr = s.recvfrom(1024) 
        print 'Process %r -> Thread %r recieved : %r' %(os.getpid(),tnum, data)
        worker(data)

open_socket(1)
$ for run in `seq 1 4`;
    do
       python above_example.py &
    done