0

非ブロッキング接続呼び出しでタイムアウトを設定しました。これは、応答しないアドレスへの接続が試行されたときに正しくタイムアウトします。ただし、接続先で接続を拒否された場合は、接続拒否のコールを返さないようです。

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;
    }
}

connect 呼び出しからは、常に EINPROGRESS が返されるように見えますが、select 呼び出しは > 0 を返し、エラーは 0 に設定されます。

これをブロッキング接続呼び出しに変更すると、接続呼び出しからすぐに CONNECTIONREFUSED の戻りコードが返されます。

4

2 に答える 2

1

socklen_t len = 0; 間違っています。これは、socklen_t len = sizeof(int); に設定する必要があります。

この値を設定すると問題が修正され、select 呼び出しから正しいリターン コード (CONNREFUSED) が設定されました。

于 2013-05-08T13:21:08.070 に答える