• 多路复用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 }
  • 相关阅读:
    js 和 jquery的宽高
    client、offset、scroll
    web开发中会话跟踪的方法有哪些
    前端需要注意哪些SEO
    ES6 Set和Map数据结构
    ES6实现数组去重
    ES6 Symbol
    ES6对象的拓展
    ES6数组的拓展
    ES6函数的拓展
  • 原文地址:https://www.cnblogs.com/chenyang920/p/5483394.html
Copyright © 2020-2023  润新知