epoll模型
int epoll_create(int maxevent) //创建一个epoll的句柄 然后maxevent表示监听的数目的大小
int epoll_ctl(int epollfd,int op,int fd,struct epoll_event *event) //epoll的事件注册函数
/*
epollfd 为epoll_create()的返回值
op 表示为相应的操作
fd 为套接字
*event 表示监听什么事件
*/
OP 有
EPOLL_CTL_ADD:注册新的fd到epfd中;
EPOLL_CTL_MOD:修改已经注册的fd的监听事件;
EPOLL_CTL_DEL:从epfd中删除一个fd;
int epoll_wait(int epollfd,struct epoll_event *event,int maxevents,int timeout);
/*
epollfd epoll_create的返回值
*event 从内核得到时间的集合
maxevents 告诉内核event多大 不能大于epoll_create()中的maxevent
timeout 表示等待的时间-1表示阻塞 0表示立即返回
*/
epoll_event结构体
1 struct epoll_event { 2 __uint32_t events; /* Epoll events */ 3 epoll_data_t data; /* User data variable */ 4 };
1 typedef union epoll_data 2 { 3 void *ptr; 4 int fd; 5 uint32_t u32; 6 uint64_t u64; 7 } epoll_data_t;
其中epoll_event 结构体中的events参数的值是宏定义:
EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里
data.h
1 #ifndef DATA_H 2 #define DATA_H 3 #include <string.h> 4 #include <stdio.h> 5 #include <sys/epoll.h> 6 #include <sys/stat.h> 7 #include <stdlib.h> 8 #include <errno.h> 9 #include <netinet/in.h> 10 #include <sys/socket.h> 11 #include <unistd.h> 12 #include <arpa/inet.h> 13 #include <assert.h> 14 #include <sys/types.h> 15 16 #define IP "127.0.0.1" 17 #define PORT 4578 18 #define maxn 1100 19 #define MAXLINE 100 20 #define BACKLOG 5 21 #define EPOLLEVENTS 1120 22 #define _EVENTS 100 23 #endif
server.c
1 #include "data.h" 2 static void epoll_accept(int sockfd); 3 static void submit_to_check(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf); 4 static void submit_to_read(int epollfd,int conn,char *buf); 5 static void submit_to_write(int epollfd,int conn,char *buf); 6 static void submit_to_accept(int epollfd,int conn); 7 static void change_event(int epollfd,int conn,int ser_event); 8 static void change_delete(int epollfd,int conn,int ser_event); 9 static void add_event(int epollfd,int sockfd,int ser_event); 10 11 static int init() 12 { 13 int sockfd; 14 struct sockaddr_in server_in; 15 if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1) 16 { 17 fprintf(stderr,"socket fail,error %s",strerror(errno)); 18 return -1; 19 } 20 bzero(&server_in,sizeof(server_in)); 21 server_in.sin_family = AF_INET; 22 server_in.sin_port = htons(PORT); 23 inet_pton(AF_INET,IP,&server_in.sin_addr); 24 if(bind(sockfd,(struct sockaddr*)&server_in,sizeof(server_in)) == -1) 25 { 26 fprintf(stderr,"bind fail,error %s",strerror(errno)); 27 return -1; 28 } 29 listen(sockfd,BACKLOG); 30 return sockfd; 31 } 32 33 static void epoll_accept(int sockfd) 34 { 35 int epollfd; 36 char buf[maxn]; 37 memset(buf,0,sizeof(buf)); 38 struct epoll_event events[_EVENTS]; 39 epollfd = epoll_create(EPOLLEVENTS); 40 int ret; 41 add_event(epollfd,sockfd,EPOLLIN); 42 for(;;) 43 { 44 ret = epoll_wait(epollfd,events,_EVENTS,-1); 45 submit_to_check(epollfd,events,ret,sockfd,buf); 46 } 47 close(epollfd); 48 } 49 static void submit_to_check(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf) 50 { 51 int i; 52 int fd; 53 for(i=0;i<num;i++) 54 { 55 fd = events[i].data.fd; 56 if((fd == sockfd) && (events[i].events&EPOLLIN)) 57 { 58 submit_to_accept(epollfd,sockfd); 59 } 60 else if(events[i].events & EPOLLIN) 61 { 62 submit_to_read(epollfd,fd,buf); 63 } 64 else if(events[i].events & EPOLLOUT) 65 { 66 submit_to_write(epollfd,fd,buf); 67 } 68 } 69 } 70 static void submit_to_read(int epollfd,int conn,char *buf) 71 { 72 int n; 73 n = read(conn,buf,maxn); 74 if(n == 0) 75 { 76 fprintf(stderr,"client close! "); 77 close(conn); 78 change_delete(epollfd,conn,EPOLLIN); 79 } 80 else if(n == -1) 81 { 82 fprintf(stderr,"read error "); 83 close(conn); 84 change_delete(epollfd,conn,EPOLLIN); 85 } 86 else 87 { 88 fprintf(stderr,"read message is %s ",buf); 89 change_event(epollfd,conn,EPOLLOUT); 90 } 91 } 92 static void submit_to_write(int epollfd,int conn,char *buf) 93 { 94 int n; 95 n = write(conn,buf,strlen(buf)); 96 if(n == -1) 97 { 98 printf("server closed! "); 99 close(conn); 100 change_delete(epollfd,conn,EPOLLOUT); 101 } 102 else 103 { 104 change_event(epollfd,conn,EPOLLIN); 105 } 106 memset(buf,'