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

ACE proactor example相关推荐

  1. 基于ACE Proactor框架下高并发、大容量吞吐程序设计既最近的一个产品开发总结

    Reactor与 Proactor 基本概念 在高性能的I/O设计中,有两个比较著名的模式Reactor和Proactor模式,其中Reactor模式用于同步I/O,而Proactor运用于异步I/O ...

  2. ACE Proactor框架

    ACE Proactor简介  前摄式I/O模型可以在多个I/O句柄上并行地发起一个货多个异步I/O操作,而无需等待它们完成.在每个操作完成时,OS会通知应用定义的完成处理器,由它随后对已完成的I/O ...

  3. ACE中的Proactor和Reactor

    ACE中的Proactor和Reactor ACE_Select_Reactor是除Windows之外所有平台使用的默认反应器实现,在这些系统上最终会用select()系统函数进行等待.在Window ...

  4. ACE之Proactor模式使用实例

    // ACE_Proactor_Client.cpp : 定义控制台应用程序的入口点. //#include "stdafx.h"#include "ace/Messag ...

  5. ACE前摄器Proactor模式

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明 http://egeho123.blogbus.com/logs/10780720.html ACE前摄器Proactor模式 当 O ...

  6. 图解VC++6.0和ACE 5.4 开发入门

    一 工具和下载 工具和环境: Win7, VC++6, ACE5.4 可在Win7下运行的VC6下载: http://blog.csdn.net/bcbobo21cn/article/details/ ...

  7. 两种高性能I/O设计模式(Reactor/Proactor)的比较

    综述 这篇文章探讨并比较两种用于TCP服务器的高性能设计模式. 除了介绍现有的解决方案,还提出了一种更具伸缩性,只需要维护一份代码并且跨平台的解决方案(含代码示例),以及其在不同平台上的微调. 此文还 ...

  8. 高性能I/O设计模式Reactor和Proactor

    昨天购买了<程序员>杂志 2007.4期,第一时间去翻阅了一遍,其中有一篇<两种高性能I/O设计模式的比较>令人眼睛一亮,这是一篇译文,偶最近在一直想认真看看这方面的文章很久了 ...

  9. ACE入门---很好的文章

    转自:http://www.cnblogs.com/dubingsky/archive/2009/07/22/1528292.html ACE编译 1. 设置环境变量 在操作系统添加一个名为ACE_R ...

最新文章

  1. 关闭Vue计算属性自带的缓存功能
  2. ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061)解决办法
  3. Intel Edison学习笔记(二)—— 入门环境配置
  4. kubernetes视频教程笔记 (38)-高可用的K8S构建-系统初始化
  5. 飞机大战java实训报告_java飞机大战实训报告.docx
  6. FlexPaper — 可以用来仿豆丁网、百度文库的PDF在线阅读功能
  7. 学生成绩管理信息系统
  8. windows下cmd下载文件
  9. struts1和struts2的区别
  10. HTTP 405 Method Not Allowed问题的解决
  11. 手把手逆向Playcanvas天空盒编码(一次乌龙的任务)
  12. matlab结构力学仿真,MATLAB在结构力学分析中应用.doc
  13. 国内的IT生意还真TMD难做,想生存发展大家还得多思考一下,出路在哪里?稍微迷茫了一点点...
  14. 基于Echarts实现可视化数据大屏大数据平台车辆监控系统HTML模板
  15. 【技术文档】centernet(姿态估计)
  16. 骞云科技SmartCMP v3.5版本正式发布
  17. 统计建模与R软件-第三章习题答案
  18. HTML网页设计:爱护动物题材——保护动物大象(6页) HTML网页设计结课作业 web课程设计网页规划与设计 网页设计成品DW静态网页
  19. 个体功能网络分区的分割方法
  20. 共振峰检测matlab百度文库,毕业设计论文-基于MATLAB的语音共振峰的估计.doc

热门文章

  1. 《STL源码剖析》学习--traits
  2. 【多线程】阻塞队列的C++多线程 实现 BlockingQueue
  3. faster rcnn源码解读总结
  4. Caffe学习系列(3):视觉层(Vision Layers)及参数
  5. 视觉检索:视频多帧排序
  6. Chrome DevTools 之 Network,网络加载分析利器
  7. LaTeX技巧24:LaTeX常用命令集锦
  8. 较高人工智能的人机博弈程序实现(多个算法结合)含C++源码
  9. 深度学习(二十二)Dropout浅层理解
  10. 2018年创业最火热点的是什么?看到这个你可能就知道哪方面发展最热了