多路复用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!
");
 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,'',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
",strerror(errno));
118         return;
119     }
120     else
121     {
122         printf("accept a new client:%s :%d
",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
",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,'',sizeof(buf));
 35     add_event(epollfd,STDIN_FILENO,EPOLLIN);
 36     for(;;)
 37     {
 38         fprintf(stderr,"Please input message!
");
 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,'',sizeof(buf));
 64     int n;
 65     n = read(fd,buf,maxn);
 66     if(n == 0)
 67     {
 68         fprintf(stderr,"server close.
");
 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 }
原文地址:https://www.cnblogs.com/chenyang920/p/5483394.html