The most obvious result of switching our sockets to nonblocking is significantly improved performance. With blocking sockets, we specified timeouts of five seconds. This meant that if a function were going to fail because the network operation did not complete in time, it would take five seconds.
With nonblocking sockets, these function calls fail immediately. Thus we finish our receive loops faster—the last iteration of the loop that would previously block until the timeout expired now immediately returns an error. This saves us five seconds every time a receive operation fails because there’s no data to receive.
As it turns out, our application already has the right architecture to support nonblocking mode. In Chapter 10, we implemented a polling architecture that checked each socket’s I/O readiness before we attempt read or write operations. This is exactly the architecture needed for nonblocking sockets.
We will need to change how we handle connections. In previous
versions, the application attempted to connect and blocked until the
three-way handshake completed or until a timeout occurred. In
nonblocking mode, we need to make several calls to
NetLibSocketConnect before the connection is
The first call to this function initiates the three-way handshake and
returns the error
attempts return this error until the connection is established. Then,
the next call to