0%

connect_nonb的问题

linux socket API connect函数,在socket是堵塞模式下,该API是不允许设置超时时间的,一个经常的实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include	"unp.h"

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, (struct sockaddr *) 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);
}

这是Unix-Network-Programming书上给的一个示例程序,但要注意,实现过程中采用了select函数,所以sockfd不能超过1024,否则会出问题