Linux epoll 非阻塞connect

为什么需要非阻塞connect?

  1. 建立当前连接与其浪费等待,不如同时做些其它有意义的工作;
  2. 可以异步建立多个连接;
  3. 可以借助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》

发表评论

电子邮件地址不会被公开。 必填项已用*标注