【问题标题】:BSD socket connect + select (client)BSD套接字连接+选择(客户端)
【发布时间】:2017-10-10 23:15:44
【问题描述】:

下面的代码一定有问题,但我似乎无法将客户端连接、非阻塞与 select 语句结合使用。请忽略下面缺少的错误处理。

我似乎有两个问题 1. 如果我尝试在 Internet 服务器上连接端口 80,则选择块直到超时 (60) 2. 尝试连接 127.0.0.1 上现有或不存在的端口总是立即返回选择,无法区分连接成功或失败。

我对 BSD 非阻塞结合 select 的理解缺少什么?

fd_set readfds;
FD_ZERO(&readfds);

struct timeval tv;
tv.tv_sec = 60;
tv.tv_usec = 0;

struct sockaddr_in dest;
int socketFD = socket(AF_INET, SOCK_STREAM, 0);

memset(&dest, 0, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr("127.0.0.1");
dest.sin_port = htons(9483);

long arg;
arg = fcntl(socketFD, F_GETFL, NULL);
arg |= O_NONBLOCK;
fcntl(socketFD, F_SETFL, arg);

if (connect(socketFD, (struct sockaddr *)&dest, sizeof(struct sockaddr))<0 && errno == EINPROGRESS) {

    //now add it to the read set
    FD_SET(socketFD, &readfds);
    int res = select(socketFD+1, &readfds, NULL, NULL, &tv);

    int error = errno;
    if (res>0 && FD_ISSET(socketFD, &readfds)) {
        NSLog(@"errno: %d", error); //Always 36
    }
}

【问题讨论】:

    标签: sockets bsd


    【解决方案1】:

    errno 在您最初尝试设置为connect 时设置为合法:也就是说,它正在进行中。然后您拨打select。由于select 没有失败,errno 没有被重置。系统调用仅在失败时设置errno;他们没有在成功时清除它。

    connect 可能已成功完成。你没有检查那个。您应该使用SO_ERROR 添加对getsockopt 的调用以确定它是否有效。这将返回套接字上的错误状态。

    另一个重要说明。根据手册页 (https://www.freebsd.org/cgi/man.cgi?query=connect&sektion=2),您应该使用 writefds 来等待 connect 的完成。不知道readfds会不会正确上报状态。

    [EINPROGRESS]   The socket is non-blocking and the connection cannot
                    be completed immediately.  It is possible to select(2)
                    for completion by selecting the socket for writing.
    

    另请参阅这个非常相似的问题。 Using select() for non-blocking sockets to connect always returns 1

    【讨论】:

    • 优秀的答案!谢谢吉尔!
    猜你喜欢
    • 2015-02-08
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    • 2021-02-03
    • 2013-04-21
    • 2017-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多