📜 ⬆️ ⬇️

Determining the blocking mode of a TCP socket under Windows

Those who work with TCP sockets know that the socket can work in blocking or nonblocking mode. Windows-sockets, after creation, are in blocking mode, but they can be converted to non-blocking function ioctlsocket ().

When working on one project, I had a task to determine in which mode the socket, provided by the DLL function, works. Those. besides the socket itself, I did not have any information and they came in an unpredictable mode.

Under * nix, blocking mode is determined without any problems by calling the fcntl () function, but under WinSock2 nothing of the kind has been found, and there’s nothing on the forums “Windows doesn’t have no one answered.
')
But the method of determining does exist:

// GetBlockingMode : 1 - nonblocking | 0 - blocking | -1 - error | -2 - timeout reseted! int GetBlockingMode(int Sock) { int iSize, iValOld, iValNew, retgso; iSize = sizeof(iValOld); retgso = getsockopt(Sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&iValOld, &iSize); // Save current timeout value if (retgso == SOCKET_ERROR) return (-1); iValNew = 1; retgso = setsockopt(Sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&iValNew, iSize); // Set new timeout to 1 ms if (retgso == SOCKET_ERROR) return (-1); // Ok! Try read 0 bytes. char buf[1]; // 1 - why not :) int retrcv = recv(Sock, buf, 0, MSG_OOB); // try read MSG_OOB int werr = WSAGetLastError(); retgso = setsockopt(Sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&iValOld, iSize); // Set timeout to initial value if (retgso == SOCKET_ERROR) return (-2); if (werr == WSAENOTCONN) return (-1); if (werr == WSAEWOULDBLOCK) return 1; return 0; } 

The function takes the socket number and returns 1 if the socket is in nonblocking mode, 0 is blocking, -1 if a detection error occurred, and -2 if the socket after the mode definition is left with a small timeout.

In short, the sequence of actions is as follows:

1. Save the socket timeout value (by default there is 0 - “wait forever”).
2. Set the timeout to 1 millisecond.
3. We read from socket 0 (zero) byte of out of band data. An explanation is needed here: If OOB data is transmitted, the function may lie, but I have never encountered OOB since Windows NT4 crashed into a blue screen while trying to accept this ( WinNuke ).
4. We get an error that occurred as a result of reading.
5. Restore the old timeout value of the socket.
6. We look at what a reading error we had: if WSAEWOULDBLOCK, then the socket is in nonblocking mode, as required.

The disadvantages of this method, in addition to the already mentioned MSG_OOB, include the detection delay of 1 millisecond and the non-zero probability of spoiling the socket read timeout (although the load test has never revealed this behavior).

Source: https://habr.com/ru/post/335762/


All Articles