I've been doing a lot of reading on blocking vs non-blocking sockets for udp, but am having a hard time understanding the merits of one over the other. the overwhelming majority of comments on the internet seem to indicate that non-blocking is better, but aren't very specific as to what scenarios they would be better in and I've found no references so far as to when blocking is preferred. my hope with this question is that the community may be able to shine a little light on this subject.
a little background on my own problem set, so that answers could potentially be applied specifically as well as to the general nature of the question. i have a udp server that i'm writing that will have 40 connections on a local lan whereby a constant stream of data will be flowing in. data rates will be around 250MB/s avg with peaks to 500+Mb/s with the avg datagram size at around 1400 bytes. processing of the datagrams is light, but due to the large volume of msgs efficiency and performance are a high priority in order to prevent dropped packets.
as I've not been able to really find any contextual information for something resembling this particular problem set, I've had to make a few guesses based on what I've been able to glean about blocking vs non-blocking. i'll just end this with what my current hypothesis is, and then open it up to your input. basically, since this will be an almost constant stream of packets on every connection, i'm thinking a blocking socket would be preferable due to the fact that the time any recv function will actually spend blocked would be very very minimal vs. using an event based model which would have an overwhelming amount of triggers in asyncrhonous mode. I feel my true problem set will most likely be priority management for the 40 threads i'm planning on using to read from the sockets... making sure each get their share of CPU time. I may be incorrect in my approach and ideas, so i'm hoping and would be very appreciative if the community could help shine some light on the matter.
~edit~
while I am concerned with how threading design will influence/integrate with the blocking/non blocking question. I really am mostly concerned with how blocking/non blocking should be viewed from the perspective of my problem set. if threading does indeed become an issue, I can go with a thread-pool solution.
~edit2~
first, wanted to say tank you for the responses so far. a few of you have mentioned that the single-thread/socket model with this many sockets may be a bad idea and i admit that i was tentative with the solution myself. however, in one of the links in nikolai's reponse, the author discusses a single-thread/socket model and links to a very interesting paper that i thought i would link to here as it dispels a lot of myths that i held about threads vs event based models: why events are a bad idea
The UDP Receive block configures and opens an interface to a specified remote address using the UDP protocol. The configuration and initialization occur once at the start of the model's execution. The block acquires data either in blocking mode or nonblocking mode during the model's run time.
Description. The UDP Send block transmits an input data vector as a UDP packet to a remote IP network port. The remote IP port number to which the block sends the UDP packets is tunable in the generated code.
In blocking socket mode, a system call event halts the execution until an appropriate reply has been received. In non-blocking sockets, it continues to execute even if the system call has been invoked and deals with its reply appropriately later.
To mark a socket as non-blocking, we use the fcntl system call. Here's an example: int flags = guard(fcntl(socket_fd, F_GETFL), "could not get file flags"); guard(fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK), "could not set file flags"); Here's a complete example.
Not an answer, just some links if you don't yet have them in your bookmarks:
The C10K problem by Dan Kegel,
High-Performance Server Architecture by Jeff Darcy,
Advanced poll APIs: epoll(4)
, kqueue(2)
.
As dumb as it may sound, but I totally missed that you are working with UDP, so ...
Since there are no protocol-level connections in UDP, and unless you have to work on different ports, you don't need 40 sockets on the server. Just one UDP "server" socket will do for all the clients. You can block on this one socket all you like just make sure the socket receive buffer is large enough to accommodate traffic spikes and don't spend too much time processing each read.
I don't know that blocking or non-blocking has a significant performance advantage; it's more a question of what sort of things your network I/O event loops want to do:
If the only thing your network I/O thread is ever going to do is listen for incoming UDP packets on a single socket, then blocking I/O will probably work fine and will be easier to program.
If your network I/O thread needs to handle more than one socket, then blocking I/O becomes problematic, because if it is blocking on socket A, it won't get woken up to handle data arriving on socket B, or vice versa. In this case, non-blocking I/O becomes preferred, since you can do your blocking in select() or poll(), which will return whenever data is available on any of the watched sockets.
Note that even in the non-blocking case you wouldn't want to busy-loop between packets, since burning CPU cycles in thread A means they won't be available to thread B, which would hurt performance. So if you aren't blocking in recv(), be sure to block in select() or poll() instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With