You're not making fine enough distinctions among the possible return values of recv
.
There are two levels here.
The first is, you're lumping 0 and -1 together. 0 means the remote peer closed its sending half of the connection, so your code does the right thing here, closing its socket down, too. -1 means something happened besides data being received. It could be a permanent error, a temporary error, or just a notification from the stack that something happened besides data being received. Your code lumps all such possibilities together, and on top of that treats them the same as when the remote peer closes the connection.
The second level is that not all reasons for getting -1 from recv
are "errors" in the sense that the socket is no longer useful. I think if you start checking for -1 and then calling WSAGetLastError
to find out why you got -1, you'll get WSAEWOULDBLOCK
, which is normal since you have a non-blocking socket. It means the recv
call cannot return data because it would have to block your program's execution thread to do so, and you told Winsock you wanted non-blocking calls.
A naive fix is to not break out of the loop on WSAEWOULDBLOCK
but that just means you burn CPU time calling recv
again and again until it returns data. That goes against the whole point of non-blocking sockets, which is that they let your program do other things while the network is busy. You're supposed to use functions like select
, WSAAsyncSelect
or WSAEventSelect
to be notified when a call to the API function is likely to succeed again. Until then, you don't call it.
You might want to visit The Winsock Programmer's FAQ. (Disclaimer: I'm its maintainer.)