Hi,
today I decided to try nonblocking tcp socket so I could have a UI that is able to cancel the connecting operation more realiably than using a small timeout in the blocking socket in the connect function, but I found out that calling connect and checking for Done doesn't work on Windows. I found 2 threads from 2012 that mention this problem.
https://en.sfml-dev.org/forums/index.php?topic=7435.0 and
https://github.com/SFML/SFML/issues/194Were they ever fixed? Anyway, I'm no expert on windows winsock, so I empirically tested and found out that sleep() a bit after calling connect was enough to work (by work I mean, trying to send bytes worked, even though connect had returned status NotReady), so I suspect that when you call connect, the internal socket is wrongly rebuilt, so it's as if you were always restarting the operation, and it never gets done, as it takes a few milliseconds to connect. Anyway... I coded a small workaround that seems to work fine. Here's some pseudocode. Instead of the more documentation compliant code:
mySocket.setBlocking(false);
while (mySocket.connect(HOST, PORT) != sf::Socket::Status::Done);
mySocket.setBlocking(true); // I only use nonblocking during the first connection phase
I do
mySocket.setBlocking(false);
mySocket.connect(HOST, PORT);
while (!mySocket.isConnected())
{
if (IWantToCancelConnectAttempt)
{
mySocket.disconnect();
goto wherever...
}
}
mySocket.setBlocking(true);
...
where isConnected is implemented like this, which is basically a small portion of the main connect method that doesn't rebuild the socket, but rather just checks what I need
bool TcpSocket::isConnected()
{
fd_set selector;
FD_ZERO(&selector);
FD_SET(getHandle(), &selector);
timeval time{};
return select(static_cast<int>(getHandle() + 1), NULL, &selector, NULL, &time);
}
I find this documentation confusing
https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-select, but apparently timeval == NULL is used for blocking operations, but using it with 0s returns immediately.
That's it. I hope that's useful for anyone having this problem. By the way, where is the most appropriate place to post these kinds of things?