I am trying to find the best way to write a multi-threaded server in C# (running on a Windows system) capable of handling a big amount of UPD packets per second. Here are the main assumptions:
-I have hundreds of clients sending small unicast UDP packets to the server on a specific port at a very high rate.
-The network can handle the load and the NIC is fast enough to send the packets to the OS.
-Packets are independent. They can be treated separately.
-My program has to read the UPD stream as fast as possible, so that no packets are lost because of an overflow.
-One thread cannot read and process the packets as fast as the NIC receives them. The load has to be spread across all several threads.
This article https://blog.cloudflare.com/how-to-receive-a-million-packets/ explains that receiving packets from several threads (in a naive way) is not the right approach as they will waste time fighting for a lock on the UDP receive buffer. This is why Windows added the SO_REUSEADDR
and SO_EXCLUSIVEADDRUSE
options which allows different sockets to bind to a port already used by another socket. According to the same article, the SO_REUSEPORT
option on a Unix system allows the load to be evenly spread across several processes which will own a dedicated UDP receiver buffer. The dream for multithreaded UDP reception!
Someone said here SO_REUSEADDR and UDP behavior in Windows that on Windows, multicast packets will be multiplexed across the sockets while unicast packets will only be sent to the first open socket (which means only one sockets will receive all the packets?).
My question is, does Windows evenly spread the unicast load across the different sockets bound to the same port with the SO_REUSEADDR
option (if so, is it with a Round-robin system or maybe a hash function)? Is it the right way of parallelizing efficiently high-speed UDP reception?
If not, would it be better to shift the load "switch" point upstream by making the clients send to different ports (which will be read by independent sockets in separate threads on the server side)?
Thanks in advance