C

时间:2016-02-21 14:22:11

标签: c sockets tcp nonblocking

我很难理解无块套接字以及如何将它们用于网络扫描程序。我理解我应该做的是使用以下内容将套接字设置为非阻塞:

fcntl(sockfd , F_SETFL, O_NONBLOCK);

然后只需调用connect,它应该返回EINPROGRESS。 之后我应该使用这样的选择:

if (select(sockfd  + 1, NULL, &fdset, NULL, &tv) == 1)

其中tv是timeval结构的地址。

然后

getsockopt(sockfd , SOL_SOCKFD ET, SO_ERROR, &so_error, &len);

知道操作是否成功,但总是如此。

有人可以给我一个小c程序的例子 检查ip是否正常,解释整个事情? 我对如何做到这一点感到非常无能为力。

1 个答案:

答案 0 :(得分:0)

SO_ERROR返回套接字的最后一个错误代码并重置它。如果select()报告套接字是可写的,则连接成功,无需检查错误代码。如果select()报告超时,则连接仍在进行中,因此错误代码仍为EINPROGRESS,只需关闭套接字并继续。要检测连接失败,请将套接字置于fd_set的{​​{1}}参数中的exceptfds,然后仅在select()仍设置SO_ERROR时检查fd_setselect()返回时> 0

fcntl(sockfd, F_SETFL, O_NONBLOCK);

res = connect(sockfd, ...);
if (res == -1)
{
    if (errno != EINPROGRESS)
    {
        // connect failed, do something...
        return;
    }

    fd_set wfd, efd;

    FD_ZERO(&wfd);
    FD_SET(sockfd, &wfd);

    FD_ZERO(&efd);
    FD_SET(sockfd, &efd);

    timeval tv;
    ...

    res = select(sockfd+1, NULL, &wfd, &efd, &tv);
    if (res == -1)
    {
        // select failed, do something...
        close(sockfd);
        return;
    }

    if (res == 0)
    {
        // connect timed out...
        close(sockfd);
        return;
    }

    if (FD_ISSET(sockfd, &efd))
    {
        // connect failed, do something...
        getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &so_error, &len);
        close(sockfd);
        return;
    }
}

// connected !