epoll的一个使用例子

冷暖自知 提交于 2019-11-28 13:47:02

使用到主要函数有:

#include <sys/epoll.h>
int epoll_create(int size);
int epoll_create1(int flags);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
typedef union epoll_data {
  void *ptr;
  int fd;
  uint32_t u32;
  uint64_t u64;
} epoll_data_t;

struct epoll_event {
  uint32_t events; /* Epoll events */
  epoll_data_t data; /* User data variable */
};
 1 #define EPOLL_SIZE 1024
 2 int doServiceEpoll(int listenFd)
 3 {
 4     struct epoll_event events[EPOLL_SIZE];
 5 
 6     struct epoll_event event;
 7     int epollFd = epoll_create1(EPOLL_CLOEXEC);
 8     if(epollFd < 0) {
 9         ERR_EXIT("epoll_create1");
10     }
11 
12     event.data.fd = listenFd;
13     event.events = EPOLLIN|EPOLLET;
14     if(epoll_ctl(epollFd, EPOLL_CTL_ADD, listenFd, &event) < 0) {
15         ERR_EXIT("epoll_ctl");
16     }
17     
18     int epollRet;
19     int i;
20     struct sockaddr_in cliAddr;
21     socklen_t len;
22     int acceptFd;
23     int epollNum = 1;
24     int readNum;
25     while(1) {
26         epollRet = epoll_wait(epollFd, events, epollNum, -1);
27         if(epollRet < 0) {
28             ERR_EXIT("epollRet");
29         } else if(epollRet == 0) {
30             continue;
31         }
32 
33         for(i = 0; i < epollRet; i++) {
34             if(events[i].data.fd == listenFd) {
35                 memset(&cliAddr, 0, sizeof(cliAddr));
36                 len = sizeof(cliAddr);
37                 if((acceptFd = accept(listenFd, (struct sockaddr *)&cliAddr, &len)) < 0) {
38                     ERR_EXIT("accept");
39                 }
40                 printf("recv a connect from %s, port %d, fd %d\n", 
41                     inet_ntoa(cliAddr.sin_addr), ntohs(cliAddr.sin_port), acceptFd);
42                 epollNum++;  
43                 event.data.fd = acceptFd;
44                 event.events = EPOLLIN|EPOLLET;
45                 if(epoll_ctl(epollFd, EPOLL_CTL_ADD, event.data.fd , &event) < 0) {
46                     ERR_EXIT("epoll_ctl");
47                 }
48             } 
49             else if(events[i].events & EPOLLIN) {
50                 if(events[i].data.fd < 0) {
51                     continue;
52                 }
53                 readNum = handleRead(events[i].data.fd);
54                 if(readNum == READ_ERROR) {
55                     ERR_EXIT("handleRead");
56                 } else if(readNum == READ_CLOSE) {
57                     event = events[i];
58                     if(epoll_ctl(epollFd, EPOLL_CTL_DEL, event.data.fd, &event) < 0) { 
59                         ERR_EXIT("epoll_ctl");
60                     }
61                     epollNum--;
62                     printf("client closed, remove %d\n", events[i].data.fd);
63                     close(events[i].data.fd);
64                 } 
65             }
66         }
67     }    
68 }

 

1. struct epoll_event events[EPOLL_SIZE];用于返回发生了哪些事件。

2. struct epoll_event event; 是一个临时变量,用于将我们想要监视的描述符通过 epoll_ctl 添加到集合中去。

3. epollNum 表示当前监视的描述符的个数。

4. epollRet 大于0时,表示有多少个文件描述符发生相关事件。 等于0时,表示超时。

5. accept时,需要将连接套接字通过epoll_ctl 添加到集合中去。当read收到FIN时,需要将连接套接字通过epoll_ctl 从集合中删去,并close此套接字。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!