在非阻塞套接字连接中,select()始终返回1

我有这个代码段,旨在使用套接字连接连接到服务器。 但是,如果它无法在一定时间内连接到服务器,我希望它停止尝试。 我尝试使用这个非阻塞套接字和select命令执行此操作,但select总是返回1,表示当我提供的地址不存在时服务器存在。 有任何想法吗?

SOCKET tcp_client( char *hname, char *sname ) { fd_set fdset; struct sockaddr_in peer; SOCKET s; FD_ZERO(&fdset); // FD_SET(STDIN, &fdset); FD_SET(s, &fdset); errno=1; struct timeval tv; tv.tv_sec = 15; set_address( hname, sname, &peer, "tcp" ); s = socket( AF_INET, SOCK_STREAM, 0 ); int n = 1; fcntl(s, F_SETFL, O_NONBLOCK); if ( !isvalidsock( s ) ) { printf("Socket Call Failed: %s\n", strerror(errno)); return(0); } int x = 0; int status = connect( s, ( struct sockaddr * )&peer, sizeof( peer ) ); if(status < 0) { printf("Status: %i\n", status); } int retVal = select(s+1, &fdset, NULL, NULL, &tv); printf("retVal: %i\n", retVal); if (retVal == 1) { int so_error; socklen_t slen = sizeof so_error; getsockopt(s, SOL_SOCKET, SO_ERROR, &so_error, &slen); if (so_error == 0) { printf("work\n"); x =1; } else { printf("fail\n"); x = 0; } } else { printf("noSocks\n"); } if (x ==0 ) { printf("Connect Failed: %s\n", strerror(errno)); L("libOnexc: Connect to socket failed"); close(s); return(0); } return s; } 

我看到的一个问题是你在创建套接字之前在fdset中粘贴s。 你需要这样做

 FD_SET(s, &fdset); 

在创建套接字之后因为s只是一个整数,因此在调用socket()之后才会是正确的值。

编辑

像这样:

 . . . SOCKET s; errno=1; struct timeval tv; tv.tv_sec = 15; set_address( hname, sname, &peer, "tcp" ); s = socket( AF_INET, SOCK_STREAM, 0 ); int n = 1; fcntl(s, F_SETFL, O_NONBLOCK); if ( !isvalidsock( s ) ) { printf("Socket Call Failed: %s\n", strerror(errno)); return(0); } FD_ZERO(&fdset); FD_SET(s, &fdset); // don't put socket in set until it is actually created 

您需要检查套接字是否已准备好写入(第二个fd_set *参数选择),而不是读取(第一个)。