首页 > 代码库 > 由select/epoll返回的非阻塞connect还会是EINPROGRESS状态吗?
由select/epoll返回的非阻塞connect还会是EINPROGRESS状态吗?
一般情况下,我们像下面代码中所示的这样使用非阻塞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。
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。