Reputation: 1192
I have two simple wrapper classes for TCPConnection and TCPListener. The application that uses these classes is running on Windows 10 and does the following:
This works perfectly when I create the server socket using the socket() call. When I switch to the WSASocket() call (non overlapped), the send calls whether send() or WSASend() will block if there is a pending recv() or WSARecv() call that is blocking.
I'm at a loss as to what could be causing this. Its always been my understanding that sends and recvs on the same socket from different threads was ok.
Are there differences in the implementation under the hood between the posix vs WSA variants? Any idea what could cause this behavior?
Call difference is as follows:
sock = socket(AF_INET, SOCK_STREAM, IPOROTO_TCP);
sock = WSASocketW(AF_INET, SOCK_STREAM, IPOROTO_TCP, nullptr, 0, 0);
The connecting client is from Python 3.8.5
Upvotes: 3
Views: 2397
Reputation: 1192
When using WSASocket() you need to pass the WSA_FLAG_OVERLAPPED flag in order to get the same behavior as calls to socket(). Without it windows will block your WSASend() or send() calls if a WSARecv() or recv() is blocked in another thread.
I was under the assumption that if I passed the WSA_FLAG_OVERLAPPED flag all my socket operations would be overlapped (i.e. all calls to WSARecv() and WSASend() would require an OVERLAPPED structure), but that is not the case.
Correct usage:
sock = WSASocketW(AF_INET, SOCK_STREAM, IPOROTO_TCP, nullptr, 0, WSA_FLAG_OVERLAPPED);
WSABUF buf { bufferLen, bufferPtr};
DWORD bytes = 0;
DWORD flags = 0;
WSARecv(sock, &buf, 1, &bytes, &flags, nullptr, nullptr); // Thread 1
WSASend(sock, &buf, 1, &bytes, 0, nullptr, nullptr); //Thread 2
Is the same as doing:
sock = socket(AF_INET, SOCK_STREAM, IPOROTO_TCP);
recv(sock, bufferPtr, bufferLen, 0); // Thread 1
send(sock, bufferPtr, bufferLen); // Thread 2
On Windows, you just don't have access to the OVERLAPPED features.
Upvotes: 4