donalmg
donalmg

Reputation: 655

Non blocking connect call doesn't return connection refused

I have setup a timeout on a non-blocking connect call, which timesout correctly when the connection is attempted to an address that will not respond. However, when the connection is refused by the destination, it does not seem to return the connection refused call.

int x = fcntl(iSock,F_GETFL, 0);
fcntl(iSock,F_SETFL, x | O_NONBLOCK);

fd_set writeFD;

FD_ZERO(&writeFD);
FD_SET(iSock, &writeFD);

timeval timeout;
timeout.tv_sec = 30;
timeout.tv_usec = 0;

errno = 0;

if ((iStat = connect(iSock, (struct sockaddr *)&addr, sizeof(addr))) < 0)
{
    if(errno == EINPROGRESS)
    {
        if(int retval = (select (iSock+1, (fd_set *)NULL, &writeFD, (fd_set *)NULL, (struct timeval *)(&timeout))  > 0) )
        {
            socklen_t len = 0;
            int error = 0;
            if (getsockopt(iSock, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
                return (-1);

            if (error == EINPROGRESS)
            {
                close(iSock);
                errno = error;
                return (-1);
            }
            else
            {
                printf("Connected \n");
                return 0;
            }
        }
        else
        {
            printf("Not Connected - %d\n", errno);
            close(iSock);
            return iStat;
        }
    }
    else
    {
        close(iSock);
        return iStat;
    }
}

From the connect call, it always seems to return EINPROGRESS, then the select call will return > 0 with error set as 0.

When I change this to a blocking connect call, I get the return code of CONNECTIONREFUSED immediately from the connect call.

Upvotes: 0

Views: 3817

Answers (2)

DDukDDak99
DDukDDak99

Reputation: 361

I think that socklen_t len = sizeof(error); better than sizeof(int).
It is same result.

Upvotes: 0

donalmg
donalmg

Reputation: 655

The socklen_t len = 0; is incorrect. This needs to be set to socklen_t len = sizeof(int);

Setting this value fixed the issue, and the correct return code (CONNREFUSED) was set from the select call

Upvotes: 1

Related Questions