为什么需要非阻塞connect?
- 建立当前连接与其浪费等待,不如同时做些其它有意义的工作;
- 可以异步建立多个连接;
- 可以借助select、epoll等系统调用设置合适的连接超时,而阻塞情况下只得等待默认的超时;
网络上的文章大多是使用select来做非阻塞连接,对于连接出错的socket读写状态还要调用getsockopt做额外处理,比较繁琐(虽然redis的实现也是这么做的^.^);而对于被动应答式服务无需做相对复杂的处理;epoll本身支持的事件类型比较丰富,因此使用epoll则会简洁的多,需要注意的是,当且仅当epool_wait调用成功,且有可写但不可读事件,表示连接成功;否则,连接出错。epoll版本的非阻塞连接代码片段如下:
if (connect(client_sock, (sockaddr *)&sock_in, sizeof(sock_in)) == -1) { if (errno != EINPROGRESS) { close(client_sock); return -1; } int epoll_fd = epoll_create(1); epoll_event event; event.data.fd = client_sock; event.events = EPOLLIN | EPOLLOUT | EPOLLET; epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_sock, &event); /*当且仅当epool_wait调用成功,且有可写但不可读事件,表示连接成功*/ bool fail = (epoll_wait(epoll_fd, &event, 1, 10000) <= 0) || (event.events & EPOLLIN) || !(event.events & EPOLLOUT); epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_sock, NULL); close(epoll_fd); if (fail) { close(client_sock); return -1; } }
refer:
1. 《UNIX网络编程-卷一:套接字联网API》