int EpollSocket::handle_readable_event(int &epollfd, epoll_event &event, EpollSocketWatcher &socket_handler) { EpollContext *epoll_context = (EpollContext *) event.data.ptr; int fd = epoll_context->fd; int buffer_size = SS_READ_BUFFER_SIZE; char read_buffer[buffer_size]; memset(read_buffer, 0, buffer_size); int read_size = recv(fd, read_buffer, buffer_size, 0); int handle_ret = 0; if(read_size > 0) { LOG_DEBUG("read success which read size:%d", read_size); handle_ret = socket_handler.on_readable(*epoll_context, read_buffer, buffer_size, read_size); } if(read_size <= 0 /* connect close or io error*/ || handle_ret < 0) { close_and_release(epollfd, event, socket_handler); return 0; } if (handle_ret == READ_CONTINUE) { event.events = EPOLLIN | EPOLLET; } else { event.events = EPOLLOUT | EPOLLET; } epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &event); return 0; }
int EpollSocket::start_epoll(int port, EpollSocketWatcher &socket_handler, int backlog) { int sockfd = this->listen_on(port, backlog); struct epoll_event ev; int epollfd = epoll_create(10); if (epollfd == -1) { perror("epoll_create"); exit(EXIT_FAILURE); } ev.events = EPOLLIN; ev.data.fd = sockfd; if(epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &ev) == -1) { perror("epoll_ctl: listen_sock"); exit(EXIT_FAILURE); } epoll_event events[10]; while(1) { int fds_num = epoll_wait(epollfd, events, 10, -1); if(fds_num == -1) { perror("epoll_pwait"); exit(EXIT_FAILURE); } for (int i = 0; i < fds_num; i++) { if(events[i].data.fd == sockfd) { int conn_sock = accept_socket(sockfd); setNonblocking(conn_sock); LOG_DEBUG("get accept socket which listen fd:%d, conn_sock_fd:%d", sockfd, conn_sock); EpollContext *epoll_context = new EpollContext(); epoll_context->fd = conn_sock; socket_handler.on_accept(*epoll_context); epoll_event conn_sock_ev; conn_sock_ev.events = EPOLLIN | EPOLLET; conn_sock_ev.data.ptr = epoll_context; if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock, &conn_sock_ev) == -1) { perror("epoll_ctl: conn_sock"); exit(EXIT_FAILURE); } } else if(events[i].events & EPOLLIN ){ // readable EpollContext *epoll_context = (EpollContext *) events[i].data.ptr; int fd = epoll_context->fd; int buffer_size = 1024; char read_buffer[buffer_size]; memset(read_buffer, 0, buffer_size); int read_size = 0; while((read_size = recv(fd, read_buffer, buffer_size, 0)) > 0) { LOG_DEBUG("read success which read size:%d", read_size); int ret = socket_handler.on_readable(*epoll_context, read_buffer, buffer_size, read_size); if(ret != 0) { close_and_release(epollfd, events[i], socket_handler); continue; } memset(read_buffer, 0, buffer_size); // reset buffer for next read } if(read_size == 0 /* connect close*/ || (read_size == -1 && errno != EAGAIN) /* io error*/) { LOG_DEBUG("read_size not normal which size:%d", read_size); close_and_release(epollfd, events[i], socket_handler); continue; } events[i].events = EPOLLOUT | EPOLLET; epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &events[i]); } else if(events[i].events & EPOLLOUT) { // writeable EpollContext *epoll_context = (EpollContext *) events[i].data.ptr; int fd = epoll_context->fd; LOG_DEBUG("start write data"); int ret = socket_handler.on_writeable(*epoll_context); if(ret != 0) { close_and_release(epollfd, events[i], socket_handler); continue; } events[i].events = EPOLLIN | EPOLLET; epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &events[i]); } else { LOG_INFO("unkonw events :%d", events[i].events); continue; } } } }