BSD socket连接+ select(客户端)

时间:2017-10-10 12:45:44

标签: sockets bsd

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

我似乎有两个问题 1.如果我尝试连接互联网服务器上的端口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
    }
}

1 个答案:

答案 0 :(得分:1)

errno设置在您connect的原始尝试中 - 合法地:即它正在进行中。然后,您致电select。由于select 失败,因此errno未被重置。系统调用仅在失败时设置errno;他们不会在成功时明确表示。

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

另一个重要的注意事项。根据手册页(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