首页 > 代码库 > 游戏服务器学习进度之epoll

游戏服务器学习进度之epoll

epoll是Linux内核为处理大批句柄而作改进的poll,是Linux下多路复用IO接口 select/poll的增强版本,它能显著的减少程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。因为它会复用文件描述符集合来传递结果 而不是迫使开发者每次等待事件之前都必须重新准备要被侦听的文件描述符集合,另一个原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那 些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了。epoll除了提供select\poll那种IO事件的电平触发(Level Triggered)外,还提供了边沿触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减少epoll_wait/epoll_pwait的调用,提供应用程序的效率

简单写了一个范例:

  1 #include <stdio.h>  2 #include <sys/types.h>  3 #include <sys/socket.h>  4 #include <netinet/in.h>  5 #include <arpa/inet.h>  6 #include <sys/epoll.h>  7 #include <fcntl.h>  8 #include <errno.h>  9 #include <unistd.h> 10  11  12 #define BUF_SIZE 1024 13 #define EPOLL_SIZE 10000 14  15 //设置socket为非阻塞模式 16 int setnonblocking(int fd) 17 { 18     int ret; 19     ret = fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK); 20     if(ret < 0) 21     { 22         perror("set nonbock failed\n"); 23         return -1; 24     } 25  26     return 0; 27 } 28  29 //网络消息处理 30 int handle_message(int fd) 31 { 32  33 } 34  35 int main(int argc, char** argv) 36 { 37     if(argc != 2) 38     { 39         perror("Usage: port\n\n"); 40         return 1; 41     } 42  43     int listener; 44     int ret; 45     int port; 46     port = atoi(argv[1]); 47  48      49     struct sockaddr_in addr, their_addr; 50     addr.sin_family = AF_INET; 51     addr.sin_port = htons(port); 52     addr.sin_addr.s_addr = htonl(INADDR_ANY); 53  54     socklen_t socklen; 55     socklen = sizeof(struct sockaddr_in); 56   //epoll事件结构体  57     static struct epoll_event ev, events[EPOLL_SIZE]; 58    //设置为可读et模式 events告诉内核要监听的事件     59     ev.events = EPOLLIN | EPOLLET; 60  61     char message[BUF_SIZE]; 62     int epfd; 63     int client, epoll_events_count; 64  65     listener = socket(AF_INET, SOCK_STREAM, 0); 66     if(listener < 0) 67     { 68         perror("create socket failed\n"); 69         return 1; 70     } 71     setnonblocking(listener); 72      73     ret = bind(listener, (struct sockaddr*)&addr, sizeof(addr)); 74     if(ret < 0) 75     { 76         close(listener); 77         return 1; 78     } 79  80     ret = listen(listener,1); 81     if(ret < 0) 82     { 83         close(listener); 84         return 1; 85     } 86   //创建一个epoll句柄 87     epfd = epoll_create(EPOLL_SIZE); 88     if(epfd < 0) 89     { 90         return 1; 91     } 92  93     ev.data.fd = listener; 94   //epoll的三个动作 EPOLL_CTL_ADD  EPOLL_CTL_MOD  EPOLL_CTL_DEL 95     ret = epoll_ctl(epfd, EPOLL_CTL_ADD, listener, &ev); 96      97     while(1) 98     {  //等待事件的产生 99         epoll_events_count = epoll_wait(epfd, events, EPOLL_SIZE, -1);100         int i;101         for(i = 0; i < epoll_events_count; ++i)102         {103             if(events[i].data.fd == listener)104             {105                 client = accept(listener, (struct sockaddr*)&their_addr, &socklen);106                 if(client < 0)107                 {108                     109                 }110                 setnonblocking(client);111                 ev.data.fd = client;112                 113                 ret = epoll_ctl(epfd, EPOLL_CTL_ADD, client, &ev);114 115                 if(ret < 0)116                 {117 118                 }119             }120             else121             {122                 handle_message(events[i].data.fd);123             }124         }    125         126     }127 128     close(listener);129     close(epfd);130     return 0;131 }

 

游戏服务器学习进度之epoll