ACE proactor example

来源:互联网 发布:能在淘宝上发布 植树 编辑:程序博客网 时间:2024/06/16 10:44

网上看的两个好的例子-学习ACE时经常看的。

这个文章应该是介绍ACE编程的一个很好的原创文章,个人非常推荐了!

1、WIN32下面用proactor可以达到几乎RAW IOCP的效率,由于封装关系,应该是差那么一点。

 

客户端处理类的常规写法:

[cpp] view plain copy
  1. //处理客户端连接消息  
  2. class ClientHandler : public ACE_Service_Handler  
  3. {  
  4. public:  
  5. /**构造函数 
  6.  * 
  7.  * 
  8.  */  
  9. ClientHandler(unsigned int client_recv_buf_size=SERVER_CLIENT_RECEIVE_BUF_SIZE)  
  10.  :_read_msg_block(client_recv_buf_size),_io_count(0)  
  11. {  
  12. }  
  13.   
  14.   
  15. ~ClientHandler(){}  
  16.   
  17. /** 
  18.  *初始化,因为可能要用到ClientHandler内存池,而这个池又不一定要用NEW 
  19.  */  
  20. void init();  
  21.   
  22. /**清理函数,因为可能要用到内存池 
  23.  * 
  24.  */  
  25. void fini();  
  26.   
  27.   
  28. //检查是否超时的函数  
  29.   
  30. void check_time_out(time_t cur_time);  
  31.   
  32. public:  
  33.   
  34. /**客户端连接服务器成功后调用 
  35.  * 
  36.  * /param handle 套接字句柄 
  37.  * /param &message_block 第一次读到的数据(未用) 
  38.  */  
  39.   
  40.   
  41. //由Acceptor来调用!!!  
  42. virtual void open (ACE_HANDLE handle,ACE_Message_Block &message_block);  
  43.   
  44. /**处理网络读操作结束消息 
  45.  * 
  46.  * /param &result 读操作结果 
  47.  */  
  48. virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &result);  
  49.   
  50.   
  51. /**处理网络写操作结束消息 
  52.  * 
  53.  * /param &result 写操作结果 
  54.  */  
  55. virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result &result);  
  56.   
  57. private:  
  58.   
  59. //**生成一个网络读请求  
  60.  *  
  61.  * /param void   
  62.  * /return 0-成功,-1失败  
  63.  */  
  64. int  initiate_read_stream  (void);  
  65.   
  66. /**生成一个写请求 
  67.  * 
  68.  * /param mb 待发送的数据 
  69.  * /param nBytes 待发送数据大小 
  70.  * /return 0-成功,-1失败 
  71.  */  
  72. int  initiate_write_stream (ACE_Message_Block & mb, size_t nBytes );  
  73.   
  74. /** 
  75.  * 
  76.  * /return 检查是否可以删除,用的是一个引用计数。每一个外出IO的时候+1,每一个IO成功后-1 
  77.  */  
  78. int check_destroy();  
  79.   
  80. //异步读  
  81. ACE_Asynch_Read_Stream _rs;  
  82.   
  83. //异步写  
  84. ACE_Asynch_Write_Stream _ws;  
  85.   
  86. //接收缓冲区只要一个就够了,因为压根就没想过要多读,我直到现在也不是很清楚为什么要多读,多读的话要考虑很多问题  
  87. ACE_Message_Block _read_msg_block;  
  88.   
  89. //套接字句柄,这个可以不要了,因为基类就有个HANDLER在里面的。  
  90. //ACE_HANDLE _handle;  
  91.   
  92. //一个锁,客户端反正有东东要锁的,注意,要用ACE_Recursive_Thread_Mutex而不是用ACE_Thread_Mutex,这里面是可以重入的,而且在WIN32下是直接的EnterCriticalSection,可以达到很高的效率  
  93. ACE_Recursive_Thread_Mutex _lock;  
  94.   
  95. //在外IO数量,其实就是引用计数啦,没啥的。为0的时候就把这个东东关掉啦。  
  96. long _io_count;  
  97.   
  98.   
  99. //检查超时用的,过段时间没东东就CLOSE他了。  
  100.   
  101. time_t _last_net_io;  
  102.   
  103. private:  
  104.   
  105.   
  106. //本来想用另外一种模型的,只用1个或者2个外出读,后来想想,反正一般内存都是足够的,就不管了。  
  107.   
  108. //ACE_Message_Block _send_msg_blocks[2];  
  109.   
  110. //ACE_Message_Block &_sending_msg_block;  
  111.   
  112. //ACE_Message_Block &_idle_msg_block;  
  113.   
  114. private:  
  115.   
  116. public:  
  117. //TODO:move to prriva and use friend class!!!  
  118.   
  119.   
  120. //只是为了效率更高,不用STL的LIST是因为到现在我没有可用的Node_Allocator,所以效率上会有问题。  
  121. ClientHandler *_next;  
  122.   
  123. ClientHandler *next(){return _next;}  
  124.   
  125. void next(ClientHandler *obj){_next=obj;}  
  126.   
  127. };  
  128.   
  129.    
  130.   
  131. //这是具体实现,有些地方比较乱,懒得管了,锁的有些地方不对。懒得改了,反正在出错或者有瓶颈的时候再做也不迟。  
  132.   
  133. void ClientHandler::handle_read_stream (const ACE_Asynch_Read_Stream::Result &result)  
  134. {  
  135. _last_net_io=ACE_OS::time(NULL);  
  136. int byterecved=result.bytes_transferred ();  
  137. if ( (result.success ()) && (byterecved != 0))  
  138. {  
  139.  //ACE_DEBUG ((LM_DEBUG,  "Receiver completed:%d/n",byterecved));  
  140.   
  141.   
  142. //处理完数据  
  143.  if(handle_received_data()==true)  
  144.  {  
  145.   //ACE_DEBUG ((LM_DEBUG,  "go on reading.../n"));  
  146.   
  147.   
  148. //把东东推到头部,处理粘包  
  149.   _read_msg_block.crunch();  
  150.   initiate_read_stream();  
  151.  }  
  152. }  
  153.   
  154.   
  155. //这个地方不想用ACE_Atom_op,因为反正要有一个锁,而且一般都会用锁,不管了。假如不在意的话,应该直接用ACE_Atom_Op以达到最好的效率  
  156.   
  157. {  
  158.  ACE_Guard<ACE_Recursive_Thread_Mutex> locker (_lock);  
  159.  _io_count--;  
  160. }  
  161. check_destroy ();  
  162. }  
  163.   
  164. void ClientHandler::init()  
  165. {  
  166.   
  167.   
  168. //初始化数据,并不在构造函数里做。  
  169. _last_net_io=ACE_OS::time(NULL);  
  170. _read_msg_block.rd_ptr(_read_msg_block.base());  
  171. _read_msg_block.wr_ptr(_read_msg_block.base());  
  172. this->handle(ACE_INVALID_HANDLE);  
  173. }  
  174.   
  175. bool ClientHandler::handle_received_data()  
  176. {  
  177.   
  178.   
  179. ...........自己处理  
  180. return true;  
  181. }  
  182.   
  183.   
  184. //==================================================================  
  185. void ClientHandler::handle_write_stream (const ACE_Asynch_Write_Stream::Result &result)  
  186. {  
  187. //发送成功,RELEASE掉  
  188. //这个不可能有多个RELEASE,直接XX掉  
  189. //result.message_block ().release ();  
  190. MsgBlockManager::get_instance().release_msg_block(&result.message_block());  
  191.   
  192. {  
  193.  ACE_Guard<ACE_Recursive_Thread_Mutex> locker (_lock);  
  194.  _io_count--;  
  195. }  
  196. check_destroy ();  
  197. }  
  198.   
  199. //bool ClientHandler::destroy ()   
  200. //{  
  201. // FUNC_ENTER;  
  202. // ClientManager::get_instance().release_client_handle(this);  
  203. // FUNC_LEAVE;  
  204. // return false ;  
  205. //}  
  206.   
  207.   
  208. int  ClientHandler::initiate_read_stream  (void)  
  209. {  
  210. ACE_Guard<ACE_Recursive_Thread_Mutex> locker (_lock);  
  211.   
  212.   
  213. //考虑到粘包的呀  
  214. if (_rs.read (_read_msg_block, _read_msg_block.space()) == -1)  
  215. {  
  216.  ACE_ERROR_RETURN ((LM_ERROR,"%p/n","ACE_Asynch_Read_Stream::read"),-1);  
  217. }  
  218. _io_count++;  
  219. return 0;  
  220. }  
  221.   
  222. /**生成一个写请求 
  223. * 
  224. * /param mb 待发送的数据 
  225. * /param nBytes 待发送数据大小 
  226. * /return 0-成功,-1失败 
  227. */  
  228. int  ClientHandler::initiate_write_stream (ACE_Message_Block & mb, size_t nBytes )  
  229. {  
  230. ACE_Guard<ACE_Recursive_Thread_Mutex> locker (_lock);  
  231. if (_ws.write (mb , nBytes ) == -1)  
  232. {  
  233.  mb.release ();  
  234.  ACE_ERROR_RETURN((LM_ERROR,"%p/n","ACE_Asynch_Write_File::write"),-1);  
  235. }  
  236. _io_count++;  
  237. return 0;  
  238. }  
  239.   
  240. void ClientHandler::open (ACE_HANDLE handle,ACE_Message_Block &message_block)  
  241. {  
  242. //FUNC_ENTER;  
  243. _last_net_io=ACE_OS::time(NULL);  
  244. _io_count=0;  
  245. if(_ws.open(*this,this->handle())==-1)  
  246. {  
  247.  ACE_ERROR ((LM_ERROR,"%p/n","ACE_Asynch_Write_Stream::open"));  
  248. }  
  249. else if (_rs.open (*thisthis->handle()) == -1)  
  250. {  
  251.  ACE_ERROR ((LM_ERROR,"%p/n","ACE_Asynch_Read_Stream::open"));  
  252. }  
  253. else  
  254. {  
  255.  initiate_read_stream ();  
  256. }  
  257.   
  258. check_destroy();  
  259. //FUNC_LEAVE;  
  260. }  
  261.   
  262. void ClientHandler::fini()  
  263. {  
  264. }  
  265.   
  266. void ClientHandler::check_time_out(time_t cur_time)  
  267. {  
  268. //ACE_Guard<ACE_Recursive_Thread_Mutex> locker (_lock);  
  269. //ACE_DEBUG((LM_DEBUG,"cur_time is %u,last io is %u/n",cur_time,_last_net_io));  
  270.   
  271. //检测是否已经为0了  
  272. if(this->handle()==ACE_INVALID_HANDLE)  
  273.  return;  
  274. if(cur_time-_last_net_io>CLIENT_TIME_OUT_SECONDS)  
  275. {  
  276.  ACE_OS::shutdown(this->handle(),SD_BOTH);  
  277.  ACE_OS::closesocket(this->handle());  
  278.  this->handle(ACE_INVALID_HANDLE);  
  279. }  
  280. }  
  281.   
  282. int ClientHandler::check_destroy()  
  283. {  
  284. {  
  285.  ACE_Guard<ACE_Recursive_Thread_Mutex> locker (_lock);  
  286.  if (_io_count> 0)  
  287.   return 1;  
  288. }  
  289. ACE_OS::shutdown(this->handle(),SD_BOTH);  
  290. ACE_OS::closesocket(this->handle());  
  291. this->handle(ACE_INVALID_HANDLE);  
  292.   
  293.   
  294. //这个地方给内存池吧。  
  295. ClientManager::get_instance().release_client_handle(this);  
  296. //delete this;  
  297. return 0;  
  298. }  
  299.   
  300.    
  301.   
  302.   
  303. 这个也很好!ACE的好文!真是不转我觉得后悔啊!  
  304. 没啥好说的,管理所有的客户端和内存池的功能。  
  305.   
  306. class ClientManager : public SingleTon<ClientManager>  
  307. {  
  308. public:  
  309.   
  310. ClientManager():_header(NULL){}  
  311.   
  312. ~ClientManager(){}  
  313.   
  314. public:  
  315.   
  316. void init(unsigned int default_pool_size,unsigned int default_read_buf_size);  
  317.   
  318. void fini();  
  319.   
  320. public:  
  321.   
  322. ClientHandler *get_clienthandler();  
  323.   
  324. void release_client_handle(ClientHandler *client);  
  325.   
  326. void check_time_out();  
  327.   
  328. size_t get_client_count();  
  329.   
  330. private:  
  331.   
  332. ClientHandler *_header;  
  333.   
  334. std::set<ClientHandler *> _active_clients;  
  335.   
  336. ACE_Recursive_Thread_Mutex _lock;  
  337. };  
  338.   
  339.    
  340.   
  341.    
  342.   
  343. #include "clientmanager.h"  
  344. #include <ace/Guard_T.h>  
  345.   
  346. ClientHandler *ClientManager::get_clienthandler()  
  347. {  
  348. FUNC_ENTER;  
  349. ACE_Guard<ACE_Recursive_Thread_Mutex> locker(_lock);  
  350. ClientHandler *ret=NULL;  
  351. if(_header==NULL)  
  352. {  
  353.  ACE_DEBUG((LM_DEBUG,"client > max clients!!!/n"));  
  354. }  
  355. else  
  356. {  
  357.  ret=_header;  
  358.  _header=_header->next();  
  359.  ret->init();  
  360.  _active_clients.insert(ret);  
  361. }  
  362. FUNC_LEAVE;  
  363. return ret;  
  364. }  
  365.   
  366. void ClientManager::release_client_handle(ClientHandler *client)  
  367. {  
  368. //FUNC_ENTER;  
  369. ACE_Guard<ACE_Recursive_Thread_Mutex> locker(_lock);  
  370. client->fini();  
  371. client->next(_header);  
  372. _header=client;  
  373. _active_clients.erase(client);  
  374. //FUNC_LEAVE;  
  375. }  
  376.   
  377. void ClientManager::init(unsigned int default_pool_size,unsigned int default_read_buf_size)  
  378. {  
  379. //FUNC_ENTER;  
  380. for(unsigned int i=0;i<default_pool_size;i++)  
  381. {  
  382.  ClientHandler *client=new ClientHandler(default_read_buf_size);  
  383.  client->next(_header);  
  384.  _header=client;  
  385. }  
  386. //FUNC_LEAVE;  
  387. }  
  388.   
  389. void ClientManager::fini()  
  390. {  
  391. //FUNC_ENTER;  
  392. while(_header)  
  393. {  
  394.  ClientHandler *temp=_header->next();  
  395.  delete _header;  
  396.  _header=temp;  
  397. }  
  398. //FUNC_LEAVE;  
  399. }  
  400.   
  401. void ClientManager::check_time_out()  
  402. {  
  403. time_t cur_time=ACE_OS::time(NULL);  
  404. ACE_Guard<ACE_Recursive_Thread_Mutex> locker(_lock);  
  405. for(std::set<ClientHandler *>::iterator it=_active_clients.begin();it!=_active_clients.end();it++)  
  406. {  
  407.  (*it)->check_time_out(cur_time);  
  408. }  
  409. }  
  410.   
  411. size_t ClientManager::get_client_count()  
  412. {  
  413. ACE_Guard<ACE_Recursive_Thread_Mutex> locker(_lock);  
  414. return _active_clients.size();  
  415. }  
  416.   
  417.   
  418. //服务器的设计  
  419. 按照七猫的说话,这个框架可以达到IOCP的效率,真的利害!但是我也不知道真伪!所以大家不要认为是我说的阿!我没有测试过,所以也不太清楚是否真的有那么高的效率!  
  420. 没有什么可说的! 好文章!  
  421.   
  422. class MyServer : public SingleTon<MyServer >  
  423. {  
  424. public:  
  425. /**主服务器初始化工作 
  426. * 
  427. * /param *listenaddr 监听地址:"192.168.0.188:80"-在192.168.0.188的80端口进行监听 
  428. "80"-在所有IP地址的80端口进行监听 
  429. * /param numOfThreads 服务器网络消息处理的线程个数 
  430. * /return 1:成功,0或者其他值:失败 
  431. */  
  432. int init(const char *listenaddr,unsigned int numOfThreads);  
  433.   
  434. /**最后清理工作,资源释放工作 
  435.  * 
  436.  */  
  437. void fini();  
  438.   
  439. /**主服务器开始运行 
  440. * 
  441. * /return 1-成功,-1失败 
  442. */  
  443. int start();  
  444.   
  445. /**主服务器停止运行 
  446. * 
  447. */  
  448. void stop();  
  449. private:  
  450. //任务管理器(线程池)  
  451. ServerTask _task;  
  452. //监听地址  
  453. ACE_INET_Addr _listen_addr;  
  454. //网络接收器  
  455. ClientAcceptor _acceptor;  
  456. //网络消息处理线程数量  
  457. unsigned int _num_of_threads;  
  458. private:  
  459.   
  460.    
  461.   
  462. Observer _observer;  
  463.   
  464. //检查是否有客户端超时  
  465. CheckClientTimeoutHandler _check_time_out_handler;  
  466. };  
  467.   
  468.   
  469. int MyServer::init(const char *listenaddr,unsigned int numOfThreads)  
  470. {  
  471. //ACE_WIN32_Proactor *pImpl = new ACE_WIN32_Proactor;  
  472. //static ACE_Proactor proactor(pImpl,1);  
  473. //ACE_Proactor::instance( & proactor);  
  474. _listen_addr=ACE_INET_Addr(listenaddr);  
  475. //_num_of_threads=numOfThreads;  
  476. _num_of_threads=1;  
  477. _observer.init();  
  478. _syn_cms_handler.init();  
  479. _check_time_out_handler.init();  
  480. return 1;  
  481. }  
  482.   
  483. void MyServer::fini()  
  484. {  
  485. ItemManager::get_instance().purge_all_items();  
  486. _observer.fini();  
  487. _syn_cms_handler.fini();  
  488. _check_time_out_handler.fini();  
  489. }  
  490.   
  491. /**主服务器开始运行 
  492. * 
  493. * /return 1-成功,-1失败 
  494. */  
  495. int MyServer::start()  
  496. {  
  497. int Rc = _acceptor.open (_listen_addr,0,1);  
  498. if(Rc==-1)  
  499. {  
  500.  ACE_ERROR_RETURN ((LM_ERROR, "acceptor error./n"), -1);  
  501. }  
  502.   
  503.    
  504.   
  505.   
  506. //每20秒检查一次,检查是否有客户端超时  
  507. ACE_Time_Value check_client_timeout_interval(120);  
  508. Rc=ACE_Proactor::instance ()->schedule_timer (  
  509.  _check_time_out_handler,  
  510.  (void *) "timeout",  
  511.  ACE_Time_Value::zero,  
  512.  check_client_timeout_interval);  
  513. if(Rc==-1)  
  514. {  
  515.  ACE_ERROR_RETURN ((LM_ERROR, "%p/n""check_client_timeout schedule_timer"), -1);  
  516. }  
  517.   
  518. ACE_Time_Value observertime(20);  
  519. Rc=ACE_Proactor::instance ()->schedule_timer (  
  520.  _observer,  
  521.  (void *) "observer",  
  522.  ACE_Time_Value::zero,  
  523.  observertime);  
  524. if(Rc==-1)  
  525. {  
  526.  ACE_ERROR_RETURN ((LM_ERROR, "%p/n""observer schedule_timer"), -1);  
  527. }  
  528.   
  529. if (_task.activate (THR_NEW_LWP, _num_of_threads ) == -1)  
  530. {  
  531.  ACE_ERROR_RETURN ((LM_ERROR, "task start error./n""main"), -1);  
  532. }  
  533. return 1;  
  534. }  
  535. /**主服务器停止运行 
  536. * 
  537. */  
  538. void MyServer::stop()  
  539. {  
  540. ACE_Proactor::end_event_loop () ;  
  541. ACE_Thread_Manager * pTM = ACE_Thread_Manager::instance();  
  542.   
  543. pTM->wait_task ( & _task) ;  
  544. //ACE_Proactor::instance( ( ACE_Proactor* )NULL );  
  545. }  
  546.   
  547.   
  548. int ACE_TMAIN(int argc,char *argv[])  
  549. {  
  550. FUNC_ENTER;   
  551. std::cout<<"size of item is "<<sizeof(Item)<<std::endl;  
  552.   
  553. //设置日志  
  554. ACE_LOG_MSG->open (argv[0],ACE_Log_Msg::OSTREAM);  
  555. //std::ofstream myostream (SERVER_LOG_FILE_NAME, ios::out | ios::trunc);  
  556. //ACE_LOG_MSG->msg_ostream (&myostream);  
  557.   
  558. //读入配置文件  
  559. ACE_DEBUG((LM_DEBUG,"read config file from %s/n",SERVER_CONFIG_FILE));  
  560. XMLConfig::get_instance().read_config_from_xml_file(SERVER_CONFIG_FILE);  
  561.   
  562.   
  563. //初始化MSGBLOCK池  
  564. ACE_DEBUG((LM_DEBUG,"starting init MsgBlockManager.../n"));  
  565. MsgBlockManager::get_instance().init(XMLConfig::get_instance().get_num_of_msg_blocks(),XMLConfig::get_instance().get_size_of_write_msg_blocks());  
  566.   
  567. //初始化连接池  
  568. ACE_DEBUG((LM_DEBUG,"starting init ClientManager.../n"));  
  569. ClientManager::get_instance().init(XMLConfig::get_instance().get_num_of_clients(),XMLConfig::get_instance().get_size_of_client_read_buf());  
  570.   
  571.    
  572.   
  573.   
  574. //开始服务器  
  575.   
  576. ACE_DEBUG((LM_DEBUG,"starting init MyServer.../n"));  
  577. MyServer::get_instance().init(XMLConfig::get_instance().get_listen_addr(),XMLConfig::get_instance().get_num_of_proactor_threads());  
  578.   
  579. ACE_DEBUG((LM_DEBUG,"starting MyServer.../n"));  
  580. MyServer::get_instance().start();  
  581. ACE_DEBUG((LM_DEBUG,"Enter looping.../n"));  
  582.   
  583. while(true)  
  584. {  
  585.  std::cout << "Input Command=>/n" << std::flush ;  
  586.  std::string inputcmd;  
  587.  std::getline(std::cin,inputcmd);  
  588.  if(!handle_console_cmd(inputcmd))  
  589.   break;  
  590. }  
  591.   
  592. //char c ;  
  593. //std::cout << "Press any key to stop and exit=>/n" << std::flush ;  
  594. //std::cin.clear ();  
  595. //std::cin >> c ;  
  596. MyServer::get_instance().stop();  
  597. MsgBlockManager::get_instance().fini();  
  598. ClientManager::get_instance().fini();  
  599. return 1;  
  600. }  

原创粉丝点击