Question

I'm using this code to connect to a server, but it is not waiting the 10 seconds I set to timeout. It returns immediately after failing to connect.

BOOL Connect(string server, int port, int timeout)
{
    struct sockaddr_in RemoteHost;
    TIMEVAL Timeout;
    Timeout.tv_sec = timeout;
    Timeout.tv_usec = 0;
    int con_error = 0;

#ifdef W32
    WSADATA       wsd;
    if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
    {
        DEBUG(L"Failed to load Winsock!\n");
        return FALSE;
    }
#endif

    //create socket if it is not already created
    if (s == SOCKET_ERROR)
    {
        //Create socket
        s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (s == SOCKET_ERROR)
        {
            DEBUG(L"Could not create socket");
            return FALSE;
        }
    }

    //setup address structure
    if (inet_addr(server.c_str()) == INADDR_NONE)
    {
        struct hostent *he;

        //resolve the hostname, its not an ip address
        if ((he = gethostbyname(server.c_str())) == NULL)
        {
            //gethostbyname failed
            DEBUG(L"gethostbyname() - Failed to resolve hostname\n");
            return FALSE;
        }
    }   
    else//plain ip address
    {
        RemoteHost.sin_addr.s_addr = inet_addr(server.c_str());
    }

    RemoteHost.sin_family = AF_INET;
    RemoteHost.sin_port = htons(port);

    //set the socket in non-blocking
    unsigned long iMode = 1;
    int iResult = ioctlsocket(s, FIONBIO, &iMode);
    if (iResult != NO_ERROR)
    {
        DEBUGP(L"ioctlsocket failed with error: %ld\n", iResult);
        return FALSE;
    }

    //Connect to remote server
    if ((con_error=connect(s, (struct sockaddr *)&RemoteHost, sizeof(RemoteHost))) < 0)
    {
        if (con_error != EINPROGRESS)
        {
            DEBUG(L"connect() failed");
            return FALSE;
        }       
    }

    // restart the socket mode
    iMode = 0;
    iResult = ioctlsocket(s, FIONBIO, &iMode);
    if (iResult != NO_ERROR)
    {
        DEBUGP(L"ioctlsocket failed with error: %ld\n", iResult);
        return FALSE;
    }

    fd_set Write, Err;
    FD_ZERO(&Write);
    FD_ZERO(&Err);
    FD_SET(s, &Write);
    FD_SET(s, &Err);

    // check if the socket is ready
    select(0, NULL, &Write, &Err, &Timeout);
    if (FD_ISSET(s, &Write))
    {
        return TRUE;
    }
    return FALSE;
}
Was it helpful?

Solution 2

Use WSAGetLastError to find out why the call has failed. connect returns 0 on success or SOCKET_ERROR on failure.

You commented that WSAGetLastError returns WSAEWOULDBLOCK which states:

This error is returned from operations on nonblocking sockets that cannot be completed immediately, for example recv when no data is queued to be read from the socket. It is a nonfatal error, and the operation should be retried later. It is normal for WSAEWOULDBLOCK to be reported as the result from calling connect on a nonblocking SOCK_STREAM socket, since some time must elapse for the connection to be established.

So is expected behaviour on the non-blocking socket you have set up.

OTHER TIPS

When the socket is not available on the target system, it may send back an ICMP message indicating that the socket is not open and attempt to connect was failed. In this case, winsock funcitons will return immediately - it's by design.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top