As we saw in our rudis_sync server implementation, the synchronous I/O model can be a major bottleneck in handling multiple clients in a given period of time. One has to use threads to process more clients. However, there's a better way to scale our server. Instead of coping with the blocking nature of sockets, we can make our sockets non-blocking. With non-blocking sockets, any read, write, or connect operation, on the socket will return immediately, regardless of whether the operation completed successfully or not, that is, they don't block the calling code if the read and write buffers are partially filled. This is the asynchronous I/O model as no client needs to wait for their request completion, and is instead notified later of the completion or failure of the request.
The asynchronous model is very efficient compared to threads, but it...