epoll的一个使用例子
使用到主要函数有:
#include <sys/epoll.h> int epoll_create(int size); int epoll_create1(int flags); int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
typedef union epoll_data { void *ptr; int fd; uint32_t u32; uint64_t u64; } epoll_data_t; struct epoll_event { uint32_t events; /* Epoll events */ epoll_data_t data; /* User data variable */ };
1 #define EPOLL_SIZE 1024 2 int doServiceEpoll(int listenFd) 3 { 4 struct epoll_event events[EPOLL_SIZE]; 5 6 struct epoll_event event; 7 int epollFd = epoll_create1(EPOLL_CLOEXEC); 8 if(epollFd < 0) { 9 ERR_EXIT("epoll_create1"); 10 } 11 12 event.data.fd = listenFd; 13 event.events = EPOLLIN|EPOLLET; 14 if(epoll_ctl(epollFd, EPOLL_CTL_ADD, listenFd, &event) < 0) { 15 ERR_EXIT("epoll_ctl"); 16 } 17 18 int epollRet; 19 int i; 20 struct sockaddr_in cliAddr; 21 socklen_t len; 22 int acceptFd; 23 int epollNum = 1; 24 int readNum; 25 while(1) { 26 epollRet = epoll_wait(epollFd, events, epollNum, -1); 27 if(epollRet < 0) { 28 ERR_EXIT("epollRet"); 29 } else if(epollRet == 0) { 30 continue; 31 } 32 33 for(i = 0; i < epollRet; i++) { 34 if(events[i].data.fd == listenFd) { 35 memset(&cliAddr, 0, sizeof(cliAddr)); 36 len = sizeof(cliAddr); 37 if((acceptFd = accept(listenFd, (struct sockaddr *)&cliAddr, &len)) < 0) { 38 ERR_EXIT("accept"); 39 } 40 printf("recv a connect from %s, port %d, fd %d\n", 41 inet_ntoa(cliAddr.sin_addr), ntohs(cliAddr.sin_port), acceptFd); 42 epollNum++; 43 event.data.fd = acceptFd; 44 event.events = EPOLLIN|EPOLLET; 45 if(epoll_ctl(epollFd, EPOLL_CTL_ADD, event.data.fd , &event) < 0) { 46 ERR_EXIT("epoll_ctl"); 47 } 48 } 49 else if(events[i].events & EPOLLIN) { 50 if(events[i].data.fd < 0) { 51 continue; 52 } 53 readNum = handleRead(events[i].data.fd); 54 if(readNum == READ_ERROR) { 55 ERR_EXIT("handleRead"); 56 } else if(readNum == READ_CLOSE) { 57 event = events[i]; 58 if(epoll_ctl(epollFd, EPOLL_CTL_DEL, event.data.fd, &event) < 0) { 59 ERR_EXIT("epoll_ctl"); 60 } 61 epollNum--; 62 printf("client closed, remove %d\n", events[i].data.fd); 63 close(events[i].data.fd); 64 } 65 } 66 } 67 } 68 }
1. struct epoll_event events[EPOLL_SIZE];用于返回发生了哪些事件。
2. struct epoll_event event; 是一个临时变量,用于将我们想要监视的描述符通过 epoll_ctl 添加到集合中去。
3. epollNum 表示当前监视的描述符的个数。
4. epollRet 大于0时,表示有多少个文件描述符发生相关事件。 等于0时,表示超时。
5. accept时,需要将连接套接字通过epoll_ctl 添加到集合中去。当read收到FIN时,需要将连接套接字通过epoll_ctl 从集合中删去,并close此套接字。