Update:
on the client, Windows is returning WSAEWOULDBLOCK, and SocketImpl::getErrorStatus maps to that error to Socket::NotReady.
According to
https://docs.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2WSAEWOULDBLOCK is:
Resource temporarily unavailable.
This error is returned from operations on nonblocking sockets that cannot be completed immediately, for example recv when no data is queued to be read from the socket. It is a nonfatal error, and the operation should be retried later. It is normal for WSAEWOULDBLOCK to be reported as the result from calling connect on a nonblocking SOCK_STREAM socket, since some time must elapse for the connection to be established.
If I ignore this specific error message (using a break on that specific case), and if I start the server before the client, the applications proceed as expected. Starting the client before the server is ready would cause it to fail.
I closely followed what parameters are we passing into the win socket methods (in particular creation, blocking, and connect), and I haven't found anything suspicious when following along SFML's code and MS's documentation.
I found a few posts that may be related to win sockets, but I haven't quite comprehend it yet.
https://forums.codeguru.com/showthread.php?317429-Why-do-I-get-WSAEWOULDBLOCK-when-calling-recv()
https://stackoverflow.com/questions/14010285/wsaewouldblock-handlingI've also read that winapi returns WSAEWOULDBLOCK when there is nothing to read from the socket. However I tested against this by having the server populate a packet and sending it immediately after successfully accepting the connection.
Another thing that puzzles me is that I'm not seeing this bug in my actual application. I created this minimal case to investigate a different bug where I'm getting multiple callbacks from one packet. However this particular bug only occurs on the Hello World programs. The only thing that comes to mind is the complexity between the two applications. The real application essentially has a continuous loop that does a host of other things every frame. I was hoping to simulate this using thread sleep. I've attempted at higher intervals, too (up to 5 seconds).
This quote from one of the SO posts lead me to suspect that it's related to the infinite while loop.
It is a performance optimization. You can speculatively try to send synchronously (which is very fast). And only if it fails you are supposed to schedule an asynchronous IO
I'll take another look at the forum posts to see if something clicks in my head.