非阻塞 connect() 和 EINTR

问题描述 投票:0回答:1

我正在使用 Stevens 的 connect_nonb(),UNIX 网络编程:

int
connect_nonb(int sockfd, const SA *saptr, socklen_t salen, int nsec)
{
    int                     flags, n, error;
    socklen_t               len;
    fd_set                  rset, wset;
    struct timeval  tval;

    flags = Fcntl(sockfd, F_GETFL, 0);
    Fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);

    error = 0;
    if ( (n = connect(sockfd, saptr, salen)) < 0)
            if (errno != EINPROGRESS)
                    return(-1);

    /* Do whatever we want while the connect is taking place. */

    if (n == 0)
            goto done;      /* connect completed immediately */

    FD_ZERO(&rset);
    FD_SET(sockfd, &rset);
    wset = rset;
    tval.tv_sec = nsec;
    tval.tv_usec = 0;

    if ( (n = Select(sockfd+1, &rset, &wset, NULL,
                                     nsec ? &tval : NULL)) == 0) {
            close(sockfd);          /* timeout */
            errno = ETIMEDOUT;
            return(-1);
    }

    if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
            len = sizeof(error);
            if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
                    return(-1);                     /* Solaris pending error */
    } else
            err_quit("select error: sockfd not set");

done:
    Fcntl(sockfd, F_SETFL, flags);  /* restore file status flags */

    if (error) {
            close(sockfd);          /* just in case */
            errno = error;
            return(-1);
    }
    return(0);
}

此函数允许自定义 connect() 超时。如果在 select() 中阻塞等待连接成功时收到信号,则 select() 将以 -1 (EINTR) 退出。此时 select() 超时尚未到期,连接尚未成功(即目标主机可能断开连接),但后续的 getsockopt() 不会返回错误。

getsockopt() 应该返回错误还是 Stevens 代码应该检查 select() 的返回码(和 errno)?

当前,当连接到不存在的主机并且信号中断 select() 时,此函数会错误地返回成功。

c sockets select-function
1个回答
2
投票

我不确定

Select()
是什么。我认为它是某种薄包装纸围绕
select()

在大多数应用程序中,每当

select()
EINTR
失败时,您应该默默地循环并再次调用
select()
,可能是在重新计算超时之后,以考虑到先前调用
select()
中已经过了一些时间的事实。

这个案例也不例外。

select()
应该处于循环状态。

© www.soinside.com 2019 - 2024. All rights reserved.