封装的EPOLL 模型

  1. #pragmaonce
  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. #ifndefEPOLL_SIZE
  11. #defineEPOLL_SIZE4096
  12. #defineEPOLL_CONTEXT_SIZE(4096+256)
  13. #endif
  14. typedefvoid*EPollerContext;
  15. classEpoller
  16. {
  17. public:
  18. Epoller(){}
  19. virtual~Epoller(){}
  20. boolcreate()
  21. {
  22. memset(_contexts,0,sizeof(_contexts));
  23. _handle=epoll_create(EPOLL_SIZE);
  24. if(_handle==-1)
  25. {
  26. glog.log(__FUNCTION__,"Epollcreateerror,errnois%d",errno);
  27. returnfalse;
  28. }
  29. else
  30. returntrue;
  31. }
  32. voidhandle_events()
  33. {
  34. for(inti=0;i<_lastntfd;i++)
  35. {
  36. on_event(_events[i].data.fd,_events[i].events);
  37. }
  38. }
  39. intget_online_users()
  40. {
  41. intresult=0;
  42. for(inti=0;i<EPOLL_CONTEXT_SIZE;i++)
  43. {
  44. if(_contexts[i]!=0)
  45. result++;
  46. }
  47. returnresult;
  48. }
  49. public:
  50. booladd(intfd,unsignedintevents)
  51. {
  52. epoll_eventpolevt;
  53. polevt.events=events;
  54. polevt.data.fd=fd;
  55. returnctl(EPOLL_CTL_ADD,fd,polevt)==0;
  56. }
  57. booldel(intfd,unsignedintevents)
  58. {
  59. epoll_eventpolevt;
  60. polevt.events=events;
  61. polevt.data.fd=fd;
  62. returnctl(EPOLL_CTL_DEL,fd,polevt)==0;
  63. }
  64. boolmodify(intfd,unsignedintevents)
  65. {
  66. epoll_eventpolevt;
  67. polevt.events=events;
  68. polevt.data.fd=fd;
  69. returnctl(EPOLL_CTL_MOD,fd,polevt)==0;
  70. }
  71. intpoll(inttimeout=5000)
  72. {
  73. _lastntfd=epoll_wait(_handle,_events,EPOLL_SIZE,timeout);
  74. return_lastntfd;
  75. }
  76. protected:
  77. intctl(intop,intfd,structepoll_event&event)
  78. {
  79. intret=epoll_ctl(_handle,op,fd,&event);
  80. if(ret!=0)
  81. {
  82. glog.log(__FUNCTION__,"epoll_ctlfail,opis%d,fdis%d,errnois%d",op,fd,errno);
  83. }
  84. returnret;
  85. }
  86. protected:
  87. staticboolsetnonblocking(intsock)
  88. {
  89. intopts;
  90. opts=fcntl(sock,F_GETFL);
  91. if(opts<0)
  92. opts=O_NONBLOCK;
  93. else
  94. opts=opts|O_NONBLOCK;
  95. if(fcntl(sock,F_SETFL,opts)<0)
  96. {
  97. glog.log(__FUNCTION__,"setnoblockerror");
  98. returnfalse;
  99. }
  100. else
  101. returntrue;
  102. }
  103. staticboolsetreuseport(intsock)
  104. {
  105. inton=1;
  106. intret=setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(int));
  107. returnret!=-1;
  108. }
  109. protected:
  110. virtualvoidon_event(intfd,intevents){}
  111. private:
  112. int_handle;
  113. epoll_event_events[EPOLL_SIZE];
  114. int_lastntfd;
  115. protected:
  116. EPollerContext_contexts[EPOLL_CONTEXT_SIZE];
  117. EPollerContextget_context(intvalue)
  118. {
  119. return_contexts[value];
  120. }
  121. boolset_context(intvalue,EPollerContextcontext)
  122. {
  123. _contexts[value]=context;
  124. }
  125. };
  126. classExampleServer:publicEpoller
  127. {
  128. public:
  129. boolinit();
  130. voidfini();
  131. voidcheck_timeout();
  132. protected:
  133. voidon_event(intfd,intevents);
  134. private:
  135. voidadd_newsock(intsockvalue);
  136. voidremove_sock(intsockvalue);
  137. private:
  138. int_listen_handler;
  139. };
  140. #include<sys/types.h>
  141. #include<sys/socket.h>
  142. #include<netinet/in.h>
  143. #include"server.h"
  144. #include"clientmanager.h"
  145. boolExampleServer::init()
  146. {
  147. this->create();
  148. _listen_handler=socket(AF_INET,SOCK_STREAM,0);
  149. setnonblocking(_listen_handler);
  150. setreuseport(_listen_handler);
  151. sockaddr_inserveraddr;
  152. memset(&serveraddr,0,sizeof(serveraddr));
  153. serveraddr.sin_family=AF_INET;
  154. serveraddr.sin_addr.s_addr=htonl(INADDR_ANY);
  155. serveraddr.sin_port=htons(ITEMLIST_SERVER_PORT);
  156. bind(_listen_handler,(sockaddr*)&serveraddr,sizeof(serveraddr));
  157. listen(_listen_handler,ITEMCOMMENT_SERVER_LISTEN_BACKLOG);
  158. this->add(_listen_handler,EPOLLIN|EPOLLOUT);
  159. this->set_context(_listen_handler,0);
  160. }
  161. voidExampleServer::fini()
  162. {
  163. close(_listen_handler);
  164. }
  165. voidExampleServer::add_newsock(intsockvalue)
  166. {
  167. if(sockvalue>EPOLL_CONTEXT_SIZE)
  168. {
  169. glog.log(__FUNCTION__,"newsockis%d,>%d",sockvalue,EPOLL_CONTEXT_SIZE);
  170. close(sockvalue);
  171. return;
  172. }
  173. ClientSession*newsession=gClientManager.alloc_client_session(sockvalue);
  174. if(newsession==NULL)
  175. {
  176. close(sockvalue);
  177. return;
  178. }
  179. if(add(sockvalue,EPOLLIN|EPOLLOUT))
  180. {
  181. this->set_context(sockvalue,newsession);
  182. }
  183. else
  184. {
  185. gClientManager.release_client(newsession);
  186. close(sockvalue);
  187. }
  188. }
  189. voidExampleServer::remove_sock(intsockvalue)
  190. {
  191. this->del(sockvalue,0);
  192. close(sockvalue);
  193. ClientSession*client=(ClientSession*)this->get_context(sockvalue);
  194. if(client)
  195. {
  196. gClientManager.release_client(client);
  197. }
  198. this->set_context(sockvalue,0);
  199. }
  200. voidExampleServer::on_event(intfd,intevents)
  201. {
  202. if(fd==_listen_handler)
  203. {
  204. sockaddr_insa;
  205. memset(&sa,0,sizeof(sa));
  206. socklen_tsalen=sizeof(sa);
  207. intnewsock=accept(_listen_handler,(sockaddr*)&sa,&salen);
  208. if(newsock>0)
  209. {
  210. add_newsock(newsock);
  211. }
  212. }
  213. else
  214. {
  215. ClientSession*client=(ClientSession*)this->get_context(fd);
  216. if(client!=NULL)
  217. {
  218. intnewevents=client->handle_events(fd,events);
  219. if(newevents==0)
  220. {
  221. remove_sock(fd);
  222. }
  223. else
  224. this->modify(fd,newevents);
  225. }
  226. }
  227. }
  228. voidExampleServer::check_timeout()
  229. {
  230. unsignedintcurtime=time(NULL);
  231. for(inti=0;i<EPOLL_SIZE+256;i++)
  232. {
  233. ClientSession*client=(ClientSession*)this->get_context(i);
  234. if(client!=NULL)
  235. {
  236. if(curtime-client->get_last_io_time()>ITEMINDEX_SERVER_MAX_TIMEOUT)
  237. {
  238. remove_sock(i);
  239. }
  240. }
  241. }
  242. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值