5

Is there a way to find out if a socket is already in Non-Blocking mode in Windows?

I know this can be done in case of Linux, but, I am unable to find any way for this Windows.

All my coding is in 'C' language. Is there a way?

Jay
  • 24,173
  • 25
  • 93
  • 141
  • Windows sockets are blocking by default (like BSD sockets). Can't you just use a flag to keep track? – jweyrich Oct 20 '10 at 04:03

4 Answers4

4

The only way you can check this is by doing something illegal on a nonblocking socket and checking that it fails in an expected way. Hardly the most robust design.

The socket will be blocking unless you explicitly set it nonblocking using WSAIoctl or ioctlsocket with FIONBIO. That cannot be too hard to check in your code, I would have thought. If you have to track this at runtime, a flag per socket as suggested by @jweyrich is the way to go.

Steve Townsend
  • 53,498
  • 9
  • 91
  • 140
  • 4
    A WinSock2 socket is also put into non-blocking mode if ony of the WSAAsync...() functions are called on it. – Remy Lebeau Oct 22 '10 at 00:23
  • You used to be able to call [WSAIsBlocking](https://msdn.microsoft.com/en-us/library/windows/desktop/ms741621(v=vs.85).aspx). Worth mentioning. – EntangledLoops Oct 12 '15 at 18:30
1

Just answered the same question here, so here's a copy-paste in the hopes that it helps:

Previously, you could call WSAIsBlocking to determine this. If you are managing legacy code, this may still be an option.

Otherwise, you could write a simple abstraction layer over the socket API. Since all sockets are blocking by default, you could maintain an internal flag and force all socket ops through your API so you always know the state.

Here is a cross-platform snippet to set/get the blocking mode, although it doesn't do exactly what you want on Windows:

/// @author Stephen Dunn
/// @date 10/12/15
bool set_blocking_mode(const int &socket, bool is_blocking)
{
    bool ret = true;

#ifdef WIN32
    /// @note windows sockets are created in blocking mode by default
    // currently on windows, there is no easy way to obtain the socket's current blocking mode since WSAIsBlocking was deprecated
    u_long flags = is_blocking ? 0 : 1;
    ret = NO_ERROR == ioctlsocket(socket, FIONBIO, &flags);
#else
    const int flags = fcntl(socket, F_GETFL, 0);
    if ((flags & O_NONBLOCK) && !is_blocking) { info("set_blocking_mode(): socket was already in non-blocking mode"); return ret; }
    if (!(flags & O_NONBLOCK) && is_blocking) { info("set_blocking_mode(): socket was already in blocking mode"); return ret; }
    ret = 0 == fcntl(socket, F_SETFL, is_blocking ? flags ^ O_NONBLOCK : flags | O_NONBLOCK);
#endif

    return ret;
}
EntangledLoops
  • 1,951
  • 1
  • 23
  • 36
0

From MSDN, the return value of connect():

  • On a blocking socket, the return value indicates success or failure of the connection attempt.

  • With a nonblocking socket, the connection attempt cannot be completed immediately. In this case, connect will return SOCKET_ERROR, and WSAGetLastError() will return WSAEWOULDBLOCK.

Vantomex
  • 2,247
  • 5
  • 20
  • 22
0

this is not ideal, but this worked for me

static bool is_blocking(SOCKET s) {
    /*
     * Win32 does not have a method of testing if socket was put into non-blocking state.
     */
    DWORD timeout;
    DWORD fast_check = 1;
    int tolen = sizeof(timeout);
    getsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout, &tolen);
    setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char *) &fast_check, sizeof(fast_check));
    char b;
    int r = recv(s, &b, 0, 0);
    setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char *) &timeout, sizeof(fast_check));

    if (r == 0)
        return true;
    else if (r == -1) {
        int err = WSAGetLastError();
        if (err == WSAEWOULDBLOCK) return false;
        if (err == WSAETIMEDOUT) return true;
    }
    return true;
}
ekoby
  • 1
  • 1