一般情况下,我们像下面代码中所示的这样使用非阻塞connect:
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111 |
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <fcntl.h> #include <arpa/inet.h> #include <sys/epoll.h> #include <errno.h> #define EPOLL_MAXEVENTS 64 int
main( int
argc, char
*argv[]) { int
fd, epfd, flags, status, ret, nevents, i, slen; struct
sockaddr_in addr; struct
in_addr remote_ip; struct
epoll_event ev, events[EPOLL_MAXEVENTS];; if
((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) { perror ( "socket failed" ); return
-1; } status = 1; if
(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &status, sizeof ( int ))) { perror ( "setsockopt failed" ); return
-1; } flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); memset (&addr, 0, sizeof (addr)); addr.sin_family = AF_INET; addr.sin_port = 9999; if
(inet_pton(AF_INET, "10.232.129.43" , &addr.sin_addr) <= 0) { perror ( "inet_pton error" ); return
-1; } ret = connect(fd, ( struct
sockaddr *) &addr, sizeof ( struct
sockaddr)); if
(ret == 0) { printf ( "non-blocking connect success. connect complete immediately" ); close(fd); return
-1; } if
(ret < 0 && errno
!= EINPROGRESS) { perror ( "connect error!" ); return
-1; } epfd = epoll_create(EPOLL_MAXEVENTS); ev.events = EPOLLOUT; ev.data.fd = fd; if
(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1 ) { perror ( "epoll_ctl error" ); goto
finish; } printf ( "add connect fd into epoll" ); memset (events, 0, sizeof (events)); for
(;;) { nevents = epoll_wait(epfd, events, EPOLL_MAXEVENTS, -1); if
(nevents < 0) { perror ( "epoll_wait failed" ); goto
finish; } for
(i = 0; i < nevents; i++) { if
(events[i].data.fd == fd) { if
(getsockopt(fd, SOL_SOCKET, SO_ERROR, ( void
*) &status, &slen) < 0) { perror ( "getsockopt error!" ); goto
finish; } if
(status != 0) { perror ( "connect error!" ); goto
finish; } printf ( "non-blocking connect success!" ); if
(epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) == -1 ) { perror ( "epoll_ctl error" ); return
0; } /* DO write... */ } } } finish: close(fd); close(epfd); return
0; } |
在上面的代码中需要注意几点:
1,什么时候connect返回成功?
三次握手中的client如果收到server对SYN的ACK,connect就会返回。
2,非阻塞的connect成功返回后,用getsockopt获得的SO_ERROR码还会使EINPROGRESS吗?
不会。除非是epoll设置的超时时间到达,否则epoll_wait返回fd后,表明fd已经可写,connect已经建立成功。此时如果getsockopt获取到的SO_ERROR 状态码是status表明connect已失败,不可能再是EINPROGRESS。
由select/epoll返回的非阻塞connect还会是EINPROGRESS状态吗?,布布扣,bubuko.com
由select/epoll返回的非阻塞connect还会是EINPROGRESS状态吗?
原文地址:http://www.cnblogs.com/cobbliu/p/3764603.html