zoukankan      html  css  js  c++  java
  • epoll_create, epoll_ctl和epoll_wait

    参考代码

      1 #include <iostream>
      2 #include <sys/socket.h>
      3 #include <sys/epoll.h>
      4 #include <netinet/in.h>
      5 #include <arpa/inet.h>
      6 #include <fcntl.h>
      7 #include <unistd.h>
      8 #include <stdio.h>
      9 #include <errno.h>
     10 
     11 using namespace std;
     12 
     13 #define MAXLINE 5
     14 #define OPEN_MAX 100
     15 #define LISTENQ 20
     16 #define SERV_PORT 5000
     17 #define INFTIM 1000
     18 
     19 void setnonblocking(int sock)
     20 {
     21     int opts;
     22     opts=fcntl(sock,F_GETFL);
     23     if(opts<0)
     24     {
     25         perror("fcntl(sock,GETFL)");
     26         exit(1);
     27     }
     28     opts = opts|O_NONBLOCK;
     29     if(fcntl(sock,F_SETFL,opts)<0)
     30     {
     31         perror("fcntl(sock,SETFL,opts)");
     32         exit(1);
     33     }
     34 }
     35 
     36 int main(int argc, char* argv[])
     37 {
     38     int i, maxi, listenfd, connfd, sockfd,epfd,nfds, portnumber;
     39     ssize_t n;
     40     char line[MAXLINE];
     41     socklen_t clilen;
     42 
     43 
     44     if ( 2 == argc )
     45     {
     46         if( (portnumber = atoi(argv[1])) < 0 )
     47         {
     48             fprintf(stderr,"Usage:%s portnumber/a/n",argv[0]);
     49             return 1;
     50         }
     51     }
     52     else
     53     {
     54         fprintf(stderr,"Usage:%s portnumber/a/n",argv[0]);
     55         return 1;
     56     }
     57 
     58 
     59 
     60     //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件
     61 
     62     struct epoll_event ev,events[20];
     63     //生成用于处理accept的epoll专用的文件描述符
     64 
     65     epfd=epoll_create(256);
     66     struct sockaddr_in clientaddr;
     67     struct sockaddr_in serveraddr;
     68     listenfd = socket(AF_INET, SOCK_STREAM, 0);
     69     //把socket设置为非阻塞方式
     70 
     71     //setnonblocking(listenfd);
     72 
     73     //设置与要处理的事件相关的文件描述符
     74 
     75     ev.data.fd=listenfd;
     76     //设置要处理的事件类型
     77 
     78     ev.events=EPOLLIN|EPOLLET;
     79     //ev.events=EPOLLIN;
     80 
     81     //注册epoll事件
     82 
     83     epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);
     84     bzero(&serveraddr, sizeof(serveraddr));
     85     serveraddr.sin_family = AF_INET;
     86     char *local_addr="127.0.0.1";
     87     inet_aton(local_addr,&(serveraddr.sin_addr));//htons(portnumber);
     88 
     89     serveraddr.sin_port=htons(portnumber);
     90     bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr));
     91     listen(listenfd, LISTENQ);
     92     maxi = 0;
     93     for ( ; ; ) {
     94         //等待epoll事件的发生
     95 
     96         nfds=epoll_wait(epfd,events,20,500);
     97         //处理所发生的所有事件
     98 
     99         for(i=0;i<nfds;++i)
    100         {
    101             if(events[i].data.fd==listenfd)//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口,建立新的连接。
    102 
    103             {
    104                 connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen);
    105                 if(connfd<0){
    106                     perror("connfd<0");
    107                     exit(1);
    108                 }
    109                 //setnonblocking(connfd);
    110 
    111                 char *str = inet_ntoa(clientaddr.sin_addr);
    112                 cout << "accapt a connection from " << str << endl;
    113                 //设置用于读操作的文件描述符
    114 
    115                 ev.data.fd=connfd;
    116                 //设置用于注测的读操作事件
    117 
    118                 ev.events=EPOLLIN|EPOLLET;
    119                 //ev.events=EPOLLIN;
    120 
    121                 //注册ev
    122 
    123                 epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
    124             }
    125             else if(events[i].events&EPOLLIN)//如果是已经连接的用户,并且收到数据,那么进行读入。
    126 
    127             {
    128                 cout << "EPOLLIN" << endl;
    129                 if ( (sockfd = events[i].data.fd) < 0)
    130                     continue;
    131                 if ( (n = read(sockfd, line, MAXLINE)) < 0) {
    132                     if (errno == ECONNRESET) {
    133                         close(sockfd);
    134                         events[i].data.fd = -1;
    135                     } else
    136                         std::cout<<"readline error"<<std::endl;
    137                 } else if (n == 0) {
    138                     close(sockfd);
    139                     events[i].data.fd = -1;
    140                 }
    141                 line[n] = '/0';
    142                 cout << "read " << line << endl;
    143                 //设置用于写操作的文件描述符
    144 
    145                 ev.data.fd=sockfd;
    146                 //设置用于注测的写操作事件
    147 
    148                 ev.events=EPOLLOUT|EPOLLET;
    149                 //修改sockfd上要处理的事件为EPOLLOUT
    150 
    151                 //epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
    152 
    153             }
    154             else if(events[i].events&EPOLLOUT) // 如果有数据发送
    155 
    156             {
    157                 sockfd = events[i].data.fd;
    158                 write(sockfd, line, n);
    159                 //设置用于读操作的文件描述符
    160 
    161                 ev.data.fd=sockfd;
    162                 //设置用于注测的读操作事件
    163 
    164                 ev.events=EPOLLIN|EPOLLET;
    165                 //修改sockfd上要处理的事件为EPOLIN
    166 
    167                 epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
    168             }
    169         }
    170     }
    171     return 0;
    172 }
    View Code
      1 //   
      2 // a simple echo server using epoll in linux  
      3 //   
      4 // 2009-11-05  
      5 // 2013-03-22:修改了几个问题,1是/n格式问题,2是去掉了原代码不小心加上的ET模式;
      6 // 本来只是简单的示意程序,决定还是加上 recv/send时的buffer偏移
      7 // by sparkling  
      8 //   
      9 #include <sys/socket.h>  
     10 #include <sys/epoll.h>  
     11 #include <netinet/in.h>  
     12 #include <arpa/inet.h>  
     13 #include <fcntl.h>  
     14 #include <unistd.h>  
     15 #include <stdio.h>  
     16 #include <errno.h>  
     17 #include <iostream>  
     18 using namespace std;  
     19 #define MAX_EVENTS 500  
     20 struct myevent_s  
     21 {  
     22     int fd;  
     23     void (*call_back)(int fd, int events, void *arg);  
     24     int events;  
     25     void *arg;  
     26     int status; // 1: in epoll wait list, 0 not in  
     27     char buff[128]; // recv data buffer  
     28     int len, s_offset;  
     29     long last_active; // last active time  
     30 };  
     31 // set event  
     32 void EventSet(myevent_s *ev, int fd, void (*call_back)(int, int, void*), void *arg)  
     33 {  
     34     ev->fd = fd;  
     35     ev->call_back = call_back;  
     36     ev->events = 0;  
     37     ev->arg = arg;  
     38     ev->status = 0;
     39     bzero(ev->buff, sizeof(ev->buff));
     40     ev->s_offset = 0;  
     41     ev->len = 0;
     42     ev->last_active = time(NULL);  
     43 }  
     44 // add/mod an event to epoll  
     45 void EventAdd(int epollFd, int events, myevent_s *ev)  
     46 {  
     47     struct epoll_event epv = {0, {0}};  
     48     int op;  
     49     epv.data.ptr = ev;  
     50     epv.events = ev->events = events;  
     51     if(ev->status == 1){  
    
     52         op = EPOLL_CTL_MOD;  
     53     }  
     54     else{  
     55         op = EPOLL_CTL_ADD;  
     56         ev->status = 1;  
     57     }  
     58     if(epoll_ctl(epollFd, op, ev->fd, &epv) < 0)  
     59         printf("Event Add failed[fd=%d], evnets[%d]
    ", ev->fd, events);  
     60     else  
     61         printf("Event Add OK[fd=%d], op=%d, evnets[%0X]
    ", ev->fd, op, events);  
     62 }  
     63 // delete an event from epoll  
     64 void EventDel(int epollFd, myevent_s *ev)  
     65 {  
     66     struct epoll_event epv = {0, {0}};  
     67     if(ev->status != 1) return;  
     68     epv.data.ptr = ev;  
     69     ev->status = 0;
     70     epoll_ctl(epollFd, EPOLL_CTL_DEL, ev->fd, &epv);  
     71 }  
     72 int g_epollFd;  
     73 myevent_s g_Events[MAX_EVENTS+1]; // g_Events[MAX_EVENTS] is used by listen fd  
     74 void RecvData(int fd, int events, void *arg);  
     75 void SendData(int fd, int events, void *arg);  
     76 // accept new connections from clients  
     77 void AcceptConn(int fd, int events, void *arg)  
     78 {  
     79     struct sockaddr_in sin;  
     80     socklen_t len = sizeof(struct sockaddr_in);  
     81     int nfd, i;  
     82     // accept  
     83     if((nfd = accept(fd, (struct sockaddr*)&sin, &len)) == -1)  
     84     {  
     85         if(errno != EAGAIN && errno != EINTR)  
     86         {  
     87         }
     88         printf("%s: accept, %d", __func__, errno);  
     89         return;  
     90     }  
     91     do  
     92     {  
     93         for(i = 0; i < MAX_EVENTS; i++)  
     94         {  
     95             if(g_Events[i].status == 0)  
     96             {  
     97                 break;  
     98             }  
     99         }  
    100         if(i == MAX_EVENTS)  
    101         {  
    102             printf("%s:max connection limit[%d].", __func__, MAX_EVENTS);  
    103             break;  
    104         }  
    105         // set nonblocking
    106         int iret = 0;
    107         if((iret = fcntl(nfd, F_SETFL, O_NONBLOCK)) < 0)
    108         {
    109             printf("%s: fcntl nonblocking failed:%d", __func__, iret);
    110             break;
    111         }
    112         // add a read event for receive data  
    113         EventSet(&g_Events[i], nfd, RecvData, &g_Events[i]);  
    114         EventAdd(g_epollFd, EPOLLIN, &g_Events[i]);  
    115     }while(0);  
    116     printf("new conn[%s:%d][time:%d], pos[%d]
    ", inet_ntoa(sin.sin_addr), 
    117             ntohs(sin.sin_port), g_Events[i].last_active, i);  
    118 }  
    119 // receive data  
    120 void RecvData(int fd, int events, void *arg)  
    121 {  
    122     struct myevent_s *ev = (struct myevent_s*)arg;  
    123     int len;  
    124     // receive data
    125     len = recv(fd, ev->buff+ev->len, sizeof(ev->buff)-1-ev->len, 0);    
    126     EventDel(g_epollFd, ev);
    127     if(len > 0)
    128     {
    129         ev->len += len;
    130         ev->buff[len] = '';  
    131         printf("C[%d]:%s
    ", fd, ev->buff);  
    132         // change to send event  
    133         EventSet(ev, fd, SendData, ev);  
    134         EventAdd(g_epollFd, EPOLLOUT, ev);  
    135     }  
    136     else if(len == 0)  
    137     {  
    138         close(ev->fd);  
    139         printf("[fd=%d] pos[%d], closed gracefully.
    ", fd, ev-g_Events);  
    140     }  
    141     else  
    142     {  
    143         close(ev->fd);  
    144         printf("recv[fd=%d] error[%d]:%s
    ", fd, errno, strerror(errno));  
    145     }  
    146 }  
    147 // send data  
    148 void SendData(int fd, int events, void *arg)  
    149 {  
    150     struct myevent_s *ev = (struct myevent_s*)arg;  
    151     int len;  
    152     // send data  
    153     len = send(fd, ev->buff + ev->s_offset, ev->len - ev->s_offset, 0);
    154     if(len > 0)  
    155     {
    156         printf("send[fd=%d], [%d<->%d]%s
    ", fd, len, ev->len, ev->buff);
    157         ev->s_offset += len;
    158         if(ev->s_offset == ev->len)
    159         {
    160             // change to receive event
    161             EventDel(g_epollFd, ev);  
    162             EventSet(ev, fd, RecvData, ev);  
    163             EventAdd(g_epollFd, EPOLLIN, ev);  
    164         }
    165     }  
    166     else  
    167     {  
    168         close(ev->fd);  
    169         EventDel(g_epollFd, ev);  
    170         printf("send[fd=%d] error[%d]
    ", fd, errno);  
    171     }  
    172 }  
    173 void InitListenSocket(int epollFd, short port)  
    174 {  
    175     int listenFd = socket(AF_INET, SOCK_STREAM, 0);  
    176     fcntl(listenFd, F_SETFL, O_NONBLOCK); // set non-blocking  
    177     printf("server listen fd=%d
    ", listenFd);  
    178     EventSet(&g_Events[MAX_EVENTS], listenFd, AcceptConn, &g_Events[MAX_EVENTS]);  
    179     // add listen socket  
    180     EventAdd(epollFd, EPOLLIN, &g_Events[MAX_EVENTS]);  
    181     // bind & listen  
    182     sockaddr_in sin;  
    183     bzero(&sin, sizeof(sin));  
    184     sin.sin_family = AF_INET;  
    185     sin.sin_addr.s_addr = INADDR_ANY;  
    186     sin.sin_port = htons(port);  
    187     bind(listenFd, (const sockaddr*)&sin, sizeof(sin));  
    188     listen(listenFd, 5);  
    189 }  
    190 int main(int argc, char **argv)  
    191 {  
    192     unsigned short port = 12345; // default port  
    193     if(argc == 2){  
    194         port = atoi(argv[1]);  
    195     }  
    196     // create epoll  
    197     g_epollFd = epoll_create(MAX_EVENTS);  
    198     if(g_epollFd <= 0) printf("create epoll failed.%d
    ", g_epollFd);  
    199     // create & bind listen socket, and add to epoll, set non-blocking  
    200     InitListenSocket(g_epollFd, port);  
    201     // event loop  
    202     struct epoll_event events[MAX_EVENTS];  
    203     printf("server running:port[%d]
    ", port);  
    204     int checkPos = 0;  
    205     while(1){  
    206         // a simple timeout check here, every time 100, better to use a mini-heap, and add timer event  
    207         long now = time(NULL);  
    208         for(int i = 0; i < 100; i++, checkPos++) // doesn't check listen fd  
    209         {  
    210             if(checkPos == MAX_EVENTS) checkPos = 0; // recycle  
    211             if(g_Events[checkPos].status != 1) continue;  
    212             long duration = now - g_Events[checkPos].last_active;  
    213             if(duration >= 60) // 60s timeout  
    214             {  
    215                 close(g_Events[checkPos].fd);  
    216                 printf("[fd=%d] timeout[%d--%d].
    ", g_Events[checkPos].fd, g_Events[checkPos].last_active, now);  
    217                 EventDel(g_epollFd, &g_Events[checkPos]);  
    218             }  
    219         }  
    220         // wait for events to happen  
    221         int fds = epoll_wait(g_epollFd, events, MAX_EVENTS, 1000);  
    222         if(fds < 0){  
    223             printf("epoll_wait error, exit
    ");  
    224             break;  
    225         }  
    226         for(int i = 0; i < fds; i++){  
    227             myevent_s *ev = (struct myevent_s*)events[i].data.ptr;  
    228             if((events[i].events&EPOLLIN)&&(ev->events&EPOLLIN)) // read event  
    229             {  
    230                 ev->call_back(ev->fd, events[i].events, ev->arg);  
    231             }  
    232             if((events[i].events&EPOLLOUT)&&(ev->events&EPOLLOUT)) // write event  
    233             {  
    234                 ev->call_back(ev->fd, events[i].events, ev->arg);  
    235             }  
    236         }  
    237     }  
    238     // free resource  
    239     return 0;  
    240 }   
    View Code

    参考资料

    epoll相关资料整理

    epoll_create函数实现源码分析

    epoll_create epoll_ctl epoll_wait close epoll和select的简单比较

    epoll使用详解(精髓)

    epoll源码分析

    epoll_create函数实现源码分析

     学习使用epoll

  • 相关阅读:
    使用FolderBrowserDialog组件选择文件夹
    使用OpenFileDialog组件打开多个文
    使用OpenFileDialog组件打开对话框
    获取弹出对话框的相关返回值
    PAT 甲级 1139 First Contact (30 分)
    PAT 甲级 1139 First Contact (30 分)
    PAT 甲级 1138 Postorder Traversal (25 分)
    PAT 甲级 1138 Postorder Traversal (25 分)
    PAT 甲级 1137 Final Grading (25 分)
    PAT 甲级 1137 Final Grading (25 分)
  • 原文地址:https://www.cnblogs.com/gjianw217/p/3313222.html
Copyright © 2011-2022 走看看