1 //读超时
2 int read_timeout(int fd,unsigned int wait_seconds)
3 {
4 int ret = 0;
5 if(wait_seconds > 0)
6 {
7 fd_set read_fdset;
8 struct timeval timeout;
9
10 FD_ZERO(&read_fdset);
11 FD_SET(fd,&read_fdset);
12
13 timeout.tv_sec = wait_seconds;
14 timeout.tv_usec = 0;
15 do
16 {
17 ret = select(fd+1,&read_fdset,NULL,NULL,&timeout);
18 }while(ret < 0 && errno == EINTR)
19
20 if(ret == 0)
21 {
22 ret = -1;
23 errno = ETIMEDOUT;
24 }
25 else if(ret == 1)
26 ret = 0;
27 }
28 return ret;
29 }
30
31
32 //接收超时
33 int accept_timeout(int fd,struct sockaddr_in *addr,unsigned int wait_seconds)
34 {
35 int ret;
36 socklen_t addrlen = sizeof(struct sockaddr_in);
37
38 if(wait_seconds > 0)
39 {
40 fd_set accept_fdset;
41 struct timeval timeout;
42 FD_ZERO(&accept_fdset);
43 FD_SET(fd,&accept_fdset);
44 timeout.tv_sec = wait_seconds;
45 timeout.tv_usec = 0;
46 do
47 {
48 ret = select(fd+1,&accept_fdset,NULL,NULL,&timeout);
49 }while(ret < 0 && errno == EINTR)
50
51 if(ret == -1)
52 return -1;
53 else if(ret == 0)
54 {
55 errno = ETIMEDOUT;
56 return -1;
57 }
58 }
59 if(addr != NULL)
60 ret = accept(fd,(struct sockaddr*)addr,&addrlen);
61 else
62 ret = accept(fd,NULL,NULL);
63 if(ret == -1)
64 ERR_EXIT("accept");
65 return ret;
66 }
67
68 void activate_nonblock(int fd)
69 {
70 int ret;
71 int flags = fcntl(fd,F_GETFL);
72 if(flags == -1)
73 ERR_EXIT("fcntl");
74 flags |= O_NONBLOCK;
75 ret = fcntl(fd,F_SETFL,flags);
76 if(ret == -1)
77 ERR_EXIT("fcntl");
78 }
79
80 void deactivate_nonblock(int fd)
81 {
82 int ret;
83 int flags = fcntl(fd,F_GETFL);
84 if(flags == -1)
85 ERR_EXIT("fcntl");
86 flags &~ O_NONBLOCK;
87 ret = fcntl(fd,F_SETFL,flags);
88 if(ret == -1)
89 ERR_EXIT("fcntl");
90 }
91
92 //连接超时
93 int connect_timeout(int fd,struct sockaddr_in *addr, unsigned int wait_seconds)
94 {
95 int ret;
96 socklen_t addrlen = sizeof(struct sockaddr_in);
97
98 if(wait_seconds > 0)
99 activat_nonblock(fd);
100
101 ret = connect(fd,(struct sockaddr*)addr,addrlen);
102 if(ret < 0 && errno == EINPROGRESS)
103 {
104 fd_set connect_fdset;
105 struct timeval timeout;
106 FD_ZERO(&connect_fdset);
107 FD_SET(fd,&connect_fdset);
108 timeout.tv_sec = wait_seconds;
109 timeout.tv_usec = 0;
110 do
111 {
112 ret = select(fd+1,NULL,&connect_fdset,NULL,&timeout);
113 }while(ret < 0 && errno == EINTR)
114 if(ret == 0)
115 {
116 ret = -1;
117 errno = ETIMEDOUT;
118 }
119 else if(ret < 0)
120 return -1;
121 else if(ret == 1)
122 {
123 int err;
124 socklen_t socklen = sizeof(err);
125 int sockoptret = getsockopt(fd,SOL_SOCKET,SO_ERROR,&err,&socklen);
126 if(sockoptret == -1)
127 {
128 return -1;
129 }
130 if(err == 0)
131 ret = 0;
132 else
133 {
134 errno = err;
135 ret = -1;
136 }
137 }
138 }
139
140 if(wait_seconds > 0)
141 {
142 deactivate_nonblock(fd);
143 }
144 return ret;
145 }