2017-10-10 55 views
0

下面的代码中必须有错误,但我似乎无法使用客户端连接,非阻塞与select语句结合使用。请忽略以下缺少错误处理。BSD套接字连接+选择(客户端)

我似乎有两个问题 1.选择阻塞,直到超时(60)如果我尝试连接互联网服务器的80端口 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

errno在你原来的尝试设置为connect - 合法:即是,它正在进行。您然后致电select。由于select没有失败,因此errno未被重置。系统调用失败时仅设置errno;他们没有成功清除它。

connect可能已成功完成。你虽然没有检查。您应该添加一个电话getsockoptSO_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

+0

优秀的答案!谢谢吉尔! –

相关问题