现在的位置: 首页 > 综合 > 正文

封装的EPOLL 模型

2013年09月11日 ⁄ 综合 ⁄ 共 5144字 ⁄ 字号 评论关闭
  1. #pragma once   
  2. #include <errno.h>   
  3. #include <sys/epoll.h>   
  4. #include <sys/types.h>   
  5. #include <sys/socket.h>   
  6. #include <fcntl.h>   
  7. #include <unistd.h>   
  8. #include <string.h>   
  9. #include "log.h"   
  10.   
  11. #ifndef EPOLL_SIZE   
  12. #define EPOLL_SIZE 4096   
  13. #define EPOLL_CONTEXT_SIZE (4096+256)   
  14. #endif   
  15.   
  16. typedef void * EPollerContext;   
  17. class Epoller   
  18. {   
  19. public:   
  20. Epoller(){}   
  21. virtual ~Epoller(){}   
  22. bool create()   
  23. {   
  24.  memset(_contexts,0,sizeof(_contexts));   
  25.  _handle=epoll_create(EPOLL_SIZE);   
  26.  if(_handle==-1)   
  27.  {   
  28.   glog.log(__FUNCTION__,"Epoll create error,errno is %d",errno);   
  29.   return false;   
  30.  }   
  31.  else  
  32.   return true;   
  33. }   
  34. void handle_events()   
  35. {   
  36.  for(int i=0;i<_lastntfd;i++)   
  37.  {   
  38.   on_event(_events[i].data.fd,_events[i].events);   
  39.  }   
  40. }   
  41. int get_online_users()   
  42. {   
  43.  int result=0;   
  44.  for(int i=0;i<EPOLL_CONTEXT_SIZE;i++)   
  45.  {   
  46.   if(_contexts[i]!=0)   
  47.    result++;   
  48.  }   
  49.  return result;   
  50. }   
  51. public:   
  52. bool add(int fd,unsigned int events)   
  53. {   
  54.  epoll_event polevt;   
  55.  polevt.events=events;   
  56.  polevt.data.fd=fd;   
  57.  return ctl(EPOLL_CTL_ADD,fd,polevt)==0;   
  58. }   
  59. bool del(int fd,unsigned int events)   
  60. {   
  61.  epoll_event polevt;   
  62.  polevt.events=events;   
  63.  polevt.data.fd=fd;   
  64.  return ctl(EPOLL_CTL_DEL,fd,polevt)==0;   
  65. }   
  66. bool modify(int fd,unsigned int events)   
  67. {   
  68.  epoll_event polevt;   
  69.  polevt.events=events;   
  70.  polevt.data.fd=fd;   
  71.  return ctl(EPOLL_CTL_MOD,fd,polevt)==0;   
  72. }   
  73. int poll(int timeout=5000)   
  74. {   
  75.  _lastntfd=epoll_wait(_handle,_events,EPOLL_SIZE,timeout);   
  76.  return _lastntfd;   
  77. }   
  78. protected:   
  79. int ctl(int op, int fd, struct epoll_event &event)   
  80. {   
  81.  int ret=epoll_ctl(_handle,op,fd,&event);   
  82.  if(ret!=0)   
  83.  {   
  84.   glog.log(__FUNCTION__,"epoll_ctl fail,op is %d,fd is %d,errno is %d",op,fd,errno);   
  85.  }   
  86.  return ret;   
  87. }   
  88. protected:   
  89. static bool setnonblocking(int sock)   
  90. {   
  91.  int opts;   
  92.  opts=fcntl(sock,F_GETFL);   
  93.  if(opts<0)   
  94.   opts=O_NONBLOCK;   
  95.  else  
  96.   opts = opts|O_NONBLOCK;   
  97.  if(fcntl(sock,F_SETFL,opts)<0)   
  98.  {   
  99.   glog.log(__FUNCTION__,"setnoblock error");   
  100.   return false;   
  101.  }   
  102.  else  
  103.   return true;   
  104. }   
  105.   
  106. static bool setreuseport(int sock)   
  107. {   
  108.  int on=1;   
  109.  int ret=setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(int));   
  110.  return ret!=-1;   
  111. }   
  112.   
  113.   
  114.   
  115. protected:   
  116. virtual void on_event(int fd,int events){}   
  117. private:   
  118. int _handle;   
  119. epoll_event _events[EPOLL_SIZE];   
  120. int _lastntfd;   
  121. protected:   
  122. EPollerContext _contexts[EPOLL_CONTEXT_SIZE];   
  123. EPollerContext get_context(int value)   
  124. {   
  125.  return _contexts[value];   
  126. }   
  127. bool set_context(int value,EPollerContext context)   
  128. {   
  129.  _contexts[value]=context;   
  130. }   
  131. };   
  132.   
  133.   
  134.   
  135.   
  136.   
  137.   
  138.   
  139.   
  140. class ExampleServer : public Epoller   
  141. {   
  142. public:   
  143. bool init();   
  144. void fini();   
  145. void check_timeout();   
  146. protected:   
  147. void on_event(int fd,int events);   
  148. private:   
  149. void add_newsock(int sockvalue);   
  150. void remove_sock(int sockvalue);   
  151. private:   
  152. int _listen_handler;   
  153. };   
  154.   
  155.   
  156.   
  157.   
  158.   
  159. #include <sys/types.h>   
  160. #include <sys/socket.h>   
  161. #include <netinet/in.h>   
  162. #include "server.h"   
  163. #include "clientmanager.h"   
  164.   
  165. bool ExampleServer::init()   
  166. {   
  167. this->create();   
  168. _listen_handler=socket(AF_INET,SOCK_STREAM,0);   
  169. setnonblocking(_listen_handler);   
  170. setreuseport(_listen_handler);   
  171. sockaddr_in serveraddr;   
  172. memset(&serveraddr,0,sizeof(serveraddr));   
  173. serveraddr.sin_family = AF_INET;   
  174. serveraddr.sin_addr.s_addr=htonl(INADDR_ANY);   
  175. serveraddr.sin_port=htons(ITEMLIST_SERVER_PORT);   
  176. bind(_listen_handler,(sockaddr *)&serveraddr, sizeof(serveraddr));   
  177. listen(_listen_handler,ITEMCOMMENT_SERVER_LISTEN_BACKLOG);   
  178. this->add(_listen_handler,EPOLLIN|EPOLLOUT);   
  179. this->set_context(_listen_handler,0);   
  180. }   
  181.   
  182. void ExampleServer::fini()   
  183. {   
  184. close(_listen_handler);   
  185. }   
  186.   
  187. void ExampleServer::add_newsock(int sockvalue)   
  188. {   
  189. if(sockvalue>EPOLL_CONTEXT_SIZE)   
  190. {   
  191.  glog.log(__FUNCTION__,"newsock is %d,> %d",sockvalue,EPOLL_CONTEXT_SIZE);   
  192.  close(sockvalue);   
  193.  return;   
  194. }   
  195.   
  196. ClientSession *newsession=gClientManager.alloc_client_session(sockvalue);   
  197. if(newsession==NULL)   
  198. {   
  199.  close(sockvalue);   
  200.  return;   
  201. }   
  202. if(add(sockvalue,EPOLLIN|EPOLLOUT))   
  203. {   
  204.  this->set_context(sockvalue,newsession);   
  205. }   
  206. else  
  207. {   
  208.  gClientManager.release_client(newsession);   
  209.  close(sockvalue);        
  210. }   
  211. }   
  212.   
  213. void ExampleServer::remove_sock(int sockvalue)   
  214. {   
  215. this->del(sockvalue,0);   
  216. close(sockvalue);   
  217. ClientSession *client=(ClientSession *)this->get_context(sockvalue);   
  218. if(client)   
  219. {   
  220.  gClientManager.release_client(client);   
  221. }   
  222. this->set_context(sockvalue,0);   
  223. }   
  224.   
  225. void ExampleServer::on_event(int fd,int events)   
  226. {   
  227. if(fd==_listen_handler)   
  228. {   
  229.  sockaddr_in sa;   
  230.  memset(&sa,0,sizeof(sa));   
  231.  socklen_t salen=sizeof(sa);   
  232.  int newsock=accept(_listen_handler,(sockaddr *)&sa,&salen);   
  233.  if(newsock>0)   
  234.  {   
  235.   add_newsock(newsock);   
  236.  }   
  237. }   
  238. else  
  239. {   
  240.  ClientSession *client=(ClientSession *)this->get_context(fd);   
  241.  if(client!=NULL)   
  242.  {   
  243.   int newevents=client->handle_events(fd,events);   
  244.   if(newevents==0)   
  245.   {   
  246.    remove_sock(fd);   
  247.   }   
  248.   else  
  249.    this->modify(fd,newevents);   
  250.  }   
  251. }   
  252. }   
  253.   
  254.   
  255. void ExampleServer::check_timeout()   
  256. {   
  257. unsigned int curtime=time(NULL);   
  258. for(int i=0;i<EPOLL_SIZE+256;i++)   
  259. {   
  260.  ClientSession *client=(ClientSession *)this->get_context(i);   
  261.  if(client!=NULL)   
  262.  {   
  263.   if(curtime-client->get_last_io_time()>ITEMINDEX_SERVER_MAX_TIMEOUT)   
  264.   {   
  265.    remove_sock(i);   
  266.   }   
  267.  }   
  268. }   
  269. }   

抱歉!评论已关闭.