为什么需要非阻塞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》