多路复用I/O模型epoll() 模型 代码实现
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!\n"); 77 close(conn); 78 change_delete(epollfd,conn,EPOLLIN); 79 } 80 else if(n == -1) 81 { 82 fprintf(stderr,"read error\n"); 83 close(conn); 84 change_delete(epollfd,conn,EPOLLIN); 85 } 86 else 87 { 88 fprintf(stderr,"read message is %s\n",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!\n"); 99 close(conn); 100 change_delete(epollfd,conn,EPOLLOUT); 101 } 102 else 103 { 104 change_event(epollfd,conn,EPOLLIN); 105 } 106 memset(buf,'\0',sizeof(buf)); 107 } 108 static void submit_to_accept(int epollfd,int conn) 109 { 110 struct sockaddr_in server_in; 111 bzero(&server_in,sizeof(server_in)); 112 socklen_t socklen; 113 int afd; 114 socklen = 1; 115 if((afd = accept(conn,(struct sockaddr*)&server_in,&socklen)) == -1) 116 { 117 fprintf(stderr,"accept fail,error %s\n",strerror(errno)); 118 return; 119 } 120 else 121 { 122 printf("accept a new client:%s :%d\n",inet_ntoa(server_in.sin_addr),server_in.sin_port); 123 add_event(epollfd,afd,EPOLLIN); 124 } 125 } 126 static void change_event(int epollfd,int conn,int ser_event) 127 { 128 struct epoll_event eventfd; 129 eventfd.data.fd = conn; 130 eventfd.events = ser_event; 131 epoll_ctl(epollfd,EPOLL_CTL_MOD,conn,&eventfd); 132 } 133 static void change_delete(int epollfd,int conn,int ser_event) 134 { 135 struct epoll_event eventfd; 136 eventfd.data.fd = conn; 137 eventfd.events = ser_event; 138 epoll_ctl(epollfd,EPOLL_CTL_DEL,conn,&eventfd); 139 } 140 static void add_event(int epollfd,int sockfd,int ser_event) 141 { 142 struct epoll_event eventfd; 143 eventfd.data.fd = sockfd; 144 eventfd.events = ser_event; 145 epoll_ctl(epollfd,EPOLL_CTL_ADD,sockfd,&eventfd); 146 } 147 148 int main() 149 { 150 151 int sockfd; 152 sockfd = init(); 153 epoll_accept(sockfd); 154 close(sockfd); 155 return 0; 156 }
client.c
1 #include "data.h" 2 3 static void connect_server(int sockfd); 4 static void submit_to_check(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf); 5 static void submit_to_read(int epollfd,int fd,int sockfd,char *buf); 6 static void submit_to_write(int epollfd,int fd,int sockfd,char *buf); 7 static void change_event(int epollfd,int sockfd,int ser_event); 8 static void change_delete(int epollfd,int sockfd,int ser_event); 9 static void add_event(int epollfd,int sockfd,int ser_event); 10 11 static int init() 12 { 13 struct sockaddr_in client_in; 14 int sockfd; 15 if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1) 16 { 17 fprintf(stderr,"socket fail,error %s\n",strerror(errno)); 18 return -1; 19 } 20 bzero(&client_in,sizeof(client_in)); 21 client_in.sin_family = AF_INET; 22 client_in.sin_port = htons(PORT); 23 inet_pton(AF_INET,IP,&client_in.sin_addr); 24 connect(sockfd,(struct sockaddr*)&client_in,sizeof(client_in)) ; 25 return sockfd; 26 } 27 static void connect_server(int sockfd) 28 { 29 int epollfd; 30 struct epoll_event events[_EVENTS]; 31 epollfd = epoll_create(EPOLLEVENTS); 32 char buf[maxn]; 33 int conn; 34 memset(buf,'\0',sizeof(buf)); 35 add_event(epollfd,STDIN_FILENO,EPOLLIN); 36 for(;;) 37 { 38 fprintf(stderr,"Please input message!\n"); 39 conn = epoll_wait(epollfd,events,_EVENTS,-1); 40 submit_to_check(epollfd,events,conn,sockfd,buf); 41 } 42 close(epollfd); 43 } 44 static void submit_to_check(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf) 45 { 46 int i; 47 int fd; 48 for(i=0;i<num;i++) 49 { 50 fd = events[i].data.fd; 51 if(events[i].events & EPOLLIN) 52 { 53 submit_to_read(epollfd,fd,sockfd,buf); 54 } 55 else if(events[i].events & EPOLLOUT) 56 { 57 submit_to_write(epollfd,fd,sockfd,buf); 58 } 59 } 60 } 61 static void submit_to_read(int epollfd,int fd,int sockfd,char *buf) 62 { 63 memset(buf,'\0',sizeof(buf)); 64 int n; 65 n = read(fd,buf,maxn); 66 if(n == 0) 67 { 68 fprintf(stderr,"server close.\n"); 69 close(fd); 70 } 71 else if(n == -1) 72 { 73 perror("read error:"); 74 close(fd); 75 } 76 else 77 { 78 if(fd == STDIN_FILENO) 79 add_event(epollfd,sockfd,EPOLLOUT); 80 else 81 { 82 change_delete(epollfd,sockfd,EPOLLIN); 83 add_event(epollfd,STDOUT_FILENO,EPOLLOUT); 84 } 85 } 86 } 87 static void submit_to_write(int epollfd,int fd,int sockfd,char *buf) 88 { 89 int n; 90 n = write(fd,buf,strlen(buf)); 91 if(n == -1) 92 { 93 perror("write error:"); 94 close(fd); 95 } 96 else 97 { 98 if(fd == STDOUT_FILENO) 99 { 100 change_delete(epollfd,fd,EPOLLOUT); 101 } 102 else 103 { 104 change_event(epollfd,fd,EPOLLIN); 105 } 106 } 107 memset(buf,0,sizeof(buf)); 108 } 109 static void change_event(int epollfd,int sockfd,int ser_event) 110 { 111 struct epoll_event eventfd; 112 eventfd.data.fd = sockfd; 113 eventfd.events = ser_event; 114 epoll_ctl(epollfd,EPOLL_CTL_MOD,sockfd,&eventfd); 115 } 116 static void change_delete(int epollfd,int sockfd,int ser_event) 117 { 118 struct epoll_event eventfd; 119 eventfd.data.fd = sockfd; 120 eventfd.events = ser_event; 121 epoll_ctl(epollfd,EPOLL_CTL_DEL,sockfd,&eventfd); 122 } 123 124 static void add_event(int epollfd,int sockfd,int ser_event) 125 { 126 struct epoll_event eventfd; 127 eventfd.data.fd = sockfd; 128 eventfd.events = ser_event; 129 epoll_ctl(epollfd,EPOLL_CTL_ADD,sockfd,&eventfd); 130 } 131 int main() 132 { 133 int sockfd = init(); 134 connect_server(sockfd); 135 close(sockfd); 136 return 0; 137 }