`
famoushz
  • 浏览: 2869643 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

还是七猫的文章。七猫对服务器设计真的很值得学习[ACE高效PROACTOR编程框架七ServerExample]摘自七猫

阅读更多
最有说服力了!
先汗一个!

cpp 代码
 
  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. }  
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics