Epoll 是一种高效的管理socket的模型,相对于select和poll更加高效。数组
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) epoll_data 联合体用来保存触发事件的某个文件描述符相关的数据.数据结构
(2) epoll_event 结构体的events字段是表示感兴趣的事件和被触发的事件:socket
EPOLLIN :表示对应的文件描述符能够读; EPOLLOUT:表示对应的文件描述符能够写; EPOLLPRI:表示对应的文件描述符有紧急的数据可读 EPOLLERR:表示对应的文件描述符发生错误; EPOLLHUP:表示对应的文件描述符被挂断; EPOLLET:表示对应的文件描述符设定为edge模式
*epoll_create, epoll_create1 函数
函数声明:int epoll_create(int size)
该函数生成一个epoll专用的文件描述符,其中的参数是指定生成描述符的最大范围。函数
函数声明:int epoll_ctl(int epfd, int op, int fd, struct epoll_event event) 该函数用于控制某个文件描述符上的事件,能够注册事件,修改事件,删除事件。
参数:epfd:由 epoll_create 生成的epoll专用的文件描述符;
op:要进行的操做例如注册事件:ui
EPOLL_CTL_ADD 注册、 EPOLL_CTL_MOD 修改、 EPOLL_CTL_DEL 删除
int main() { //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件 struct epoll_event ev,events[20]; epfd=epoll_create(10000); //建立epoll句柄 listenfd = socket(AF_INET, SOCK_STREAM, 0); //把socket设置为非阻塞方式 setnonblocking(listenfd); bzero(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = INADDR_ANY; serveraddr.sin_port=htons(SERV_PORT); bind(listenfd,(struct sockaddr )&serveraddr, sizeof(serveraddr)); listen(listenfd, 255); //设置与要处理的事件相关的文件描述符 ev.data.fd=listenfd; //设置要处理的事件类型 ev.events=EPOLLIN; //注册epoll事件 epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev); for ( ; ; ) { //等待epoll事件的发生 nfds=epoll_wait(epfd,events,20,1000); //处理所发生的全部事件 for(i=0;i<nfds;++i) { if(events .data.fd==listenfd) { connfd = accept(listenfd,(struct sockaddr )&clientaddr, &clilen); if(connfd<0) { perror("connfd<0"); } setnonblocking(connfd); //设置用于读操做的文件描述符 ev.data.fd=connfd; //设置用于注测的读操做事件 ev.events=EPOLLIN|EPOLLET; //注册event epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev); } else if(events .events&EPOLLIN) { read_socket(events .data.fd); ev.data.fd=events .data.fd; ev.events=EPOLLIN|EPOLLOUT|EPOLLET; epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); } else if(events .events&EPOLLOUT) { write_socket(events .data.fd); ev.data.fd=events .data.fd; ev.events=EPOLLIN|EPOLLET; //ET模式 epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); } else { perror("other event"); } } } }