1.Epoll事件的触发模式
1.Level Trigger没有处理反复发送(效率低,开发简单,select/epoll默认触发模式)
2.Edge Trigger只发送一次(效率高,开发困难)
2.Epoll重要的API
1.int epoll_create();
2.int epoll_ctl(epfd, op, fd, struct epoll_event* event);
3.int epoll_wait(epfd, events, maxevents, timeout);
3.Epoll的事件
1.EPOLLET 边缘触发
2.EPOLLIN 读事件
3.EPOLLOUT 写事件
4.EPOLLPRI 服务中断
5.EPOLLERR 读写出错
6.EPOLLHUP 服务挂起
4.epoll_ctl相关操作
1.EPOLL_CTL_ADD 添加文件描述符
2.EPOLL_CTL_MOD 修改已存在的描述符
3.EPOLL_CTL_DEL 删除已存在的描述符
5.Epoll重要结构体
1 typedef union epoll_data { 2 void* ptr; 3 int fd; 4 uint32_t u32; 5 uint64_t u64; 6 } epoll_data_t; 7 8 struct epoll_event { 9 uint32_t events; // epoll events 10 epoll_data_t data; // user data variable 11 };
6.epoll实现高性能网络服务器
1 /** 2 epoll.c 3 */ 4 #include <stdio.h> 5 #include <errno.h> 6 #include <unistd.h> 7 #include <fcntl.h> 8 #include <string.h> 9 #include <strings.h> 10 #include <sys/types.h> 11 #include <sys/socket.h> 12 #include <netinet/in.h> 13 #include <sys/epoll.h> 14 15 #define PORT 8111 16 #define MSG_LEN 1024 17 #define MAX_EVENTS 20 18 #define TIMEOUT 500 19 20 int main(int argc, char* argv[]) 21 { 22 int ret = -1; 23 int on = 1; 24 int backlog = 10; 25 int flags = 1; 26 int socket_fd = -1; 27 int epoll_fd = -1;; 28 int event_num = 0; 29 struct epoll_event ev, events[MAX_EVENTS]; 30 struct sockaddr_in local_addr, remote_addr; 31 char buff[MSG_LEN] = { 0 }; 32 33 socket_fd = socket(AF_INET, SOCK_STREAM, 0); 34 if (socket_fd < 0) { 35 printf("create socket fd failed. "); 36 _exit(-1); 37 } 38 39 flags = fcntl(socket_fd, F_GETFL, 0); 40 fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK); 41 42 ret = setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 43 if (ret < 0) { 44 printf("set socket option failed. "); 45 } 46 47 bzero(&local_addr, sizeof(local_addr)); 48 local_addr.sin_family = AF_INET; 49 local_addr.sin_port = htons(PORT); 50 local_addr.sin_addr.s_addr = htonl(INADDR_ANY); 51 ret = bind(socket_fd, (struct sockaddr *)&local_addr, sizeof(struct sockaddr)); 52 if (ret < 0) { 53 printf("bind port[%d] failed. ", PORT); 54 _exit(-1); 55 } 56 57 ret = listen(socket_fd, backlog); 58 if (ret < 0) { 59 printf("listen socket[%d] port[%d] failed. ", socket_fd, PORT); 60 _exit(-1); 61 } 62 printf("listening on port[%d]... ", PORT); 63 64 epoll_fd = epoll_create(256); 65 ev.events = EPOLLIN; 66 ev.data.fd = socket_fd; 67 epoll_ctl(epoll_fd, EPOLL_CTL_ADD, socket_fd, &ev); 68 69 while (1) { 70 event_num = epoll_wait(epoll_fd, events, MAX_EVENTS, TIMEOUT); 71 for (int i = 0; i < event_num; ++i) 72 { 73 if (events[i].data.fd == socket_fd) { 74 socklen_t addr_len = sizeof(struct sockaddr); 75 int accept_fd = accept(socket_fd, (struct sockaddr *)&remote_addr, &addr_len); 76 flags = fcntl(accept_fd, F_GETFL, 0); 77 fcntl(accept_fd, F_SETFL, flags | O_NONBLOCK); 78 ev.events = EPOLLIN | EPOLLET; 79 ev.data.fd = accept_fd; 80 epoll_ctl(epoll_fd, EPOLL_CTL_ADD, accept_fd, &ev); 81 printf("connection[%d] estasblished... ", accept_fd); 82 } else if (events[i].events & EPOLLIN) { 83 memset(buff, 0, sizeof(buff)); 84 ret = recv(events[i].data.fd, (void *)buff, sizeof(buff), 0); 85 86 if (ret <= 0) { 87 switch (errno) { 88 case EAGAIN: 89 printf("receive EAGAIN, break... "); 90 break; 91 case EINTR: 92 do { 93 printf("index[%d] fd[%d] receive EINTR, rereceive... ", i, events[i].data.fd); 94 memset(buff, 0, sizeof(buff)); 95 ret = recv(events[i].data.fd, (void *)buff, sizeof(buff), 0); 96 } while (ret < 0 && errno == EINTR); 97 break; 98 default: 99 printf("receive ret[%d] fd[%d] errno[%d|%s] ", ret, events[i].data.fd, errno, strerror(errno)); 100 close(events[i].data.fd); 101 ev.events = EPOLLIN | EPOLLET; 102 ev.data.fd = events[i].data.fd; 103 epoll_ctl(epoll_fd, EPOLL_CTL_DEL, events[i].data.fd, &ev); 104 break; 105 } 106 } 107 108 if (ret > 0) { 109 if (ret == MSG_LEN){ 110 printf("maybe more data... "); 111 } 112 113 buff[ret] = '