找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 11683|回复: 11

采用C++的ACE库实现的一个通用的C/S架构通信程序(最终版)

[复制链接]
发表于 2008-7-13 23:21:00 | 显示全部楼层 |阅读模式
ACE自适配通信环境(ADAPTIVE Communication Environment)是可以自由使用、开放源码的面向对象(OO)框架(Framework),在其中实现了许多用于并发通信软件的核心模式。ACE提供了一组丰富的可复用C++ Wrapper Facade(包装外观)和框架组件,可跨越多种平台完成通用的通信软件任务,其中包括:事件多路分离和事件处理器分派、信号处理、服务初始化、进程间通信、共享内存管理、消息路由、分布式服务动态(重)配置、并发执行和同步,等等。ACE的目标用户是高性能和实时通信服务和应用的开发者。它简化了使用进程间通信、事件多路分离、显式动态链接和并发的OO网络应用和服务的开发。此外,通过服务在运行时与应用的动态链接,ACE还使系统的配置和重配置得以自动化。

我最近采用ACE实现了一个通用的C/S架构通信程序,具体实现简述如下:1. 服务器端:一个采用领导者/跟随者模型的线程池不断地接受从多个客户端发来的消息,并放入一个消息队列,然后又有一个采用半同步/半异步模型的线程池不断地从这个消息队列中取出消息进行处理。
服务器端代码如下:(共10个文件)
  1. ACE_Server.cpp
  2. #include "ace/SOCK_Acceptor.h"
  3. #include "ace/Acceptor.h"
  4. #include "ace/Thread_Manager.h"
  5. #include "ace/TP_Reactor.h"
  6. #include "ace/Reactor.h"
  7. #include "ace/INET_Addr.h"
  8. #include "ace/OS.h"
  9. #include "Request_Handler.h"
  10. #include "Server.h"
  11. #include "Constants.h"
  12. using namespace ACE_Server;
  13. int main(int argc, char *argv[])
  14. {
  15.         ACE_TP_Reactor tp_reactor;
  16.         ACE_Reactor reactor(&tp_reactor, 1);
  17.         ACE_Reactor::instance(&reactor, 1);
  18.         ACE_Acceptor<Request_Handler, ACE_SOCK_ACCEPTOR> acceptor;
  19.         ACE_INET_Addr addr(SERVER_PORT_NUM);
  20.         if(acceptor.open(addr) == -1)
  21.                 return -1;
  22.         Server server_tp;
  23.         server_tp.activate(THR_NEW_LWP | THR_JOINABLE, SERVER_THREAD_POOL_SIZE);
  24.         ACE_Thread_Manager::instance()->wait();
  25.         return 0;
  26. }
  27. //Constants.h
  28. #ifndef __CONSTANTS_H_
  29. #define __CONSTANTS_H_
  30. namespace ACE_Server
  31. {
  32.         static const size_t SERVER_THREAD_POOL_SIZE = 5; //进行数据接收的线程池大小
  33.         static const size_t TASK_THREAD_POOL_SIZE = 5; //进行数据处理的线程池大小
  34.         static const size_t BUFFER_SIZE = 4096; //数据缓冲区大小
  35.         static const size_t SERVER_PORT_NUM = 10101; //服务器的通信端口号
  36. }
  37. #endif
  38. //Server.h
  39. #ifndef __SERVER_H_
  40. #define __SERVER_H_
  41. #include "ace/Task.h"
  42. namespace ACE_Server
  43. {
  44.         class Server: public ACE_Task_Base
  45.         {
  46.         public:
  47.                 virtual int svc(void);
  48.         };
  49. }
  50. #endif
  51. //Server.cpp
  52. #include "ace/Reactor.h"
  53. #include "Server.h"
  54. namespace ACE_Server
  55. {
  56.         int Server::svc(void)
  57.         {
  58.                 int result = ACE_Reactor::instance()->run_reactor_event_loop();
  59.                 if(result == -1)
  60.                         return -1;
  61.                 return 0;
  62.         }
  63. }
  64. //Request_Handler.h
  65. #ifndef __REQUEST_HANDLER_H_
  66. #define __REQUEST_HANDLER_H_
  67. #include "ace/Svc_Handler.h"
  68. #include "ace/SOCK_Stream.h"
  69. #include "ace/Synch.h"
  70. #include "ace/Thread_Manager.h"
  71. #include "Task_Manager.h"
  72. namespace ACE_Server
  73. {
  74.         class Request_Handler: public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_MT_SYNCH>
  75.         {
  76.         public:
  77.                 Request_Handler(ACE_Thread_Manager *thr_mgr = 0);
  78.         protected:
  79.                 virtual int handle_input(ACE_HANDLE fd = ACE_INVALID_HANDLE);
  80.         private:
  81.                 static Task_Manager task_mgr;
  82.         };
  83. }
  84. #endif
  85. //Request_Handler.cpp
  86. #include "ace/OS.h"
  87. #include "ace/Message_Block.h"
  88. #include "ace/Thread_Manager.h"
  89. #include "ace/Svc_Handler.h"
  90. #include "ace/SOCK_Stream.h"
  91. #include "ace/Synch.h"
  92. #include "ace/Reactor.h"
  93. #include "Request_Handler.h"
  94. #include "Task_Manager.h"
  95. #include "Constants.h"
  96. namespace ACE_Server
  97. {
  98.         Task_Manager Request_Handler::task_mgr;
  99.         Request_Handler::Request_Handler(ACE_Thread_Manager *thr_mgr): ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_MT_SYNCH> (thr_mgr)
  100.         {
  101.                 this->reactor(ACE_Reactor::instance());
  102.                 task_mgr.activate();
  103.         }
  104.         int Request_Handler::handle_input(ACE_HANDLE fd)
  105.         {
  106.                 char length[4] = {0};
  107.                 if(this->peer().recv_n(length, 4) == 4)
  108.                 {
  109.                         size_t msg_len = 0;
  110.                         for(int i = 0; i < 4; i++)
  111.                         {
  112.                                 msg_len |= (size_t)length[i] << (8 * i);
  113.                         }
  114.                         char msg[BUFFER_SIZE] = {0};
  115.                         if(this->peer().recv_n(msg, msg_len) == msg_len)
  116.                         {
  117.                                 ACE_Message_Block *mb = NULL;
  118.                                 ACE_NEW_RETURN(mb, ACE_Message_Block(msg_len, ACE_Message_Block::MB_DATA, 0, msg), -1);
  119.                                 mb->wr_ptr(msg_len);
  120.                                 //
  121.                                 task_mgr.putq(mb);
  122.                                 return 0;
  123.                         }
  124.                 }
  125.                 return -1;
  126.         }
  127. }
  128. //Task_Manager.h
  129. #ifndef __TASK_MANAGER_H_
  130. #define __TASK_MANAGER_H_
  131. #include "ace/Task.h"
  132. #include "ace/Synch.h"
  133. namespace ACE_Server
  134. {
  135.         class Task_Manager: public ACE_Task<ACE_MT_SYNCH>
  136.         {
  137.         public:
  138.                 virtual int svc(void);
  139.         };
  140. }
  141. #endif
  142. //Task_Manager.cpp
  143. #include "ace/Message_Block.h"
  144. #include "Task_Manager.h"
  145. #include "Task_Worker.h"
  146. #include "Constants.h"
  147. namespace ACE_Server
  148. {
  149.         int Task_Manager::svc(void)
  150.         {
  151.                 Task_Worker task_tp;
  152.                 task_tp.activate(THR_NEW_LWP | THR_JOINABLE, TASK_THREAD_POOL_SIZE);
  153.                 while(1)
  154.                 {
  155.                         ACE_Message_Block *mb = NULL;
  156.                         if(this->getq(mb) < 0)
  157.                         {
  158.                                 task_tp.msg_queue()->deactivate();
  159.                                 task_tp.wait();
  160.                         }
  161.                         //
  162.                         task_tp.putq(mb);
  163.                 }
  164.                 return 0;
  165.         }
  166. }
  167. //Task_Worker.h
  168. #ifndef __TASK_WORKER_H_
  169. #define __TASK_WORKER_H_
  170. #include "ace/Task.h"
  171. #include "ace/Synch.h"
  172. #include "ace/Message_Block.h"
  173. namespace ACE_Server
  174. {
  175.         class Task_Worker: public ACE_Task<ACE_MT_SYNCH>
  176.         {
  177.         public:
  178.                 virtual int svc(void);
  179.         private:
  180.                 void process_task(ACE_Message_Block *mb);
  181.         };
  182. }
  183. #endif
  184. //Task_Worker.cpp
  185. #include "ace/OS.h"
  186. #include "ace/Message_Block.h"
  187. #include "Task_Worker.h"
  188. namespace ACE_Server
  189. {
  190.         int Task_Worker::svc(void)
  191.         {
  192.                 while(1)
  193.                 {
  194.                         ACE_Message_Block *mb = NULL;
  195.                         if(this->getq(mb) == -1)
  196.                         {
  197.                                 continue;
  198.                         }
  199.                         process_task(mb);
  200.                 }
  201.                 return 0;
  202.         }
  203.         void Task_Worker::process_task(ACE_Message_Block *mb)
  204.         {
  205.                 //进行数据处理,数据的起始地址为mb->rd_ptr(),长度为mb->length()
  206.                 ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%t) Processing task: %s length %d\n"), mb->rd_ptr(), mb->length()));
  207.                 ACE_OS::sleep(3); //模拟数据处理过程
  208.                 mb->release();
  209.         }
  210. }
  211. //2. 客户端:应用程序将需要发送的若干消息放入一个消息队列,然后激活一个线程来发送所有消息到服务器端。
  212. //客户端代码如下:(共4个文件)
  213. //ACE_Client.cpp
  214. #include "Client.h"
  215. using namespace ACE_Client;
  216. int main(int argc, char *argv[])
  217. {
  218.         Client client("localhost"); //服务器的IP地址或者服务器名称
  219.         for(int i = 0; i < 5; i++)
  220.         {
  221.                 char *task1 = "Is it a good day?"; //第1个task的数据
  222.                 size_t task1_len = 18; //第1个task的数据长度
  223.                 char *task1_t; //无需修改
  224.                 ACE_NEW_RETURN(task1_t, char[task1_len + 4], -1); //无需修改
  225.                 client.put_task(task1_t, task1, task1_len); //无需修改
  226.                 char *task2 = "Yeah, it really is."; //第2个task的数据
  227.                 size_t task2_len = 20; //第2个task的数据长度
  228.                 char *task2_t; //无需修改
  229.                 ACE_NEW_RETURN(task2_t, char[task2_len + 4], -1); //无需修改
  230.                 client.put_task(task2_t, task2, task2_len); //无需修改
  231.                 client.send_tasks(); //将上面的task全部发到服务器
  232.                 delete [] task1_t; //释放task1的内存
  233.                 delete [] task2_t; //释放task2的内存
  234.         }
  235.         return 0;
  236. }
  237. //Constants.h
  238. #ifndef __CONSTANTS_H_
  239. #define __CONSTANTS_H_
  240. #include "ace/Time_Value.h"
  241. namespace ACE_Client
  242. {
  243.         static const size_t BUFFER_SIZE = 4096; //数据缓冲区大小
  244.         static const size_t SERVER_PORT_NUM = 10101; //服务器的通信端口号
  245.         static const ACE_Time_Value TIME_INTERVAL(0, 1000000); //两次数据发送之间的时间间隔(0 s + 1000000 us = 1 s)
  246. }
  247. #endif
  248. //Client.h
  249. #ifndef __CLIENT_H_
  250. #define __CLIENT_H_
  251. #include "ace/Task.h"
  252. #include "ace/INET_Addr.h"
  253. #include "ace/Synch.h"
  254. namespace ACE_Client
  255. {
  256.         class Client: public ACE_Task<ACE_NULL_SYNCH>
  257.         {
  258.         public:
  259.                 Client(char *server);
  260.                 virtual int svc(void);
  261.                 char *put_task(char *msg_t, char *msg_s, size_t msg_len);
  262.                 void send_tasks(void);
  263.         private:
  264.                 ACE_INET_Addr addr;
  265.         };
  266. }
  267. #endif
  268. //Client.cpp
  269. #include "ace/OS.h"
  270. #include "ace/SOCK_Stream.h"
  271. #include "ace/SOCK_Connector.h"
  272. #include "ace/Message_Block.h"
  273. #include "ace/Thread_Manager.h"
  274. #include "ace/INET_Addr.h"
  275. #include "Constants.h"
  276. #include "Client.h"
  277. namespace ACE_Client
  278. {
  279.         Client::Client(char *server)
  280.         {
  281.                 addr = ACE_INET_Addr(SERVER_PORT_NUM, server);
  282.         }
  283.         int Client::svc(void)
  284.         {
  285.                 ACE_SOCK_Stream stream;
  286.                 ACE_SOCK_Connector connector;
  287.                 if(connector.connect(stream, addr) < 0)
  288.                 {
  289.                         return -1;
  290.                 }
  291.                 else
  292.                 {
  293.                         while(1)
  294.                         {
  295.                                 ACE_Message_Block *mb = NULL;
  296.                                 if(this->getq(mb) == -1)
  297.                                 {
  298.                                         break;
  299.                                 }
  300.                                 ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%t) Sending %s\n"), &(mb->rd_ptr()[4])));
  301.                                 stream.send_n(mb->rd_ptr(), mb->length());
  302.                                 mb->release();
  303.                                 ACE_OS::sleep(TIME_INTERVAL);
  304.                         }
  305.                 }
  306.                 stream.close();
  307.                 return 0;
  308.         }
  309.         char *Client::put_task(char *msg_t, char *msg_s, size_t msg_len)
  310.         {
  311.                 for(int i = 0; i < 4; i++)
  312.                 {
  313.                         msg_t[i] = (char)((msg_len >> (8 * i)) & 0xff);
  314.                 }
  315.                 ACE_OS::memcpy(&msg_t[4], msg_s, msg_len);
  316.                 ACE_Message_Block *mb = NULL;
  317.                 ACE_NEW_RETURN(mb, ACE_Message_Block(msg_len + 4, ACE_Message_Block::MB_DATA, 0, msg_t), 0);
  318.                 mb->wr_ptr(msg_len + 4);
  319.                 this->putq(mb);
  320.                 return msg_t;
  321.         }
  322.         void Client::send_tasks(void)
  323.         {
  324.                 this->activate();
  325.                 ACE_Thread_Manager::instance()->wait();
  326.         }
  327. }
复制代码

全部完毕,希望大家能够喜欢:) 
作者Blog:[url=http://blog.csdn.net/chenruichuan/]http://blog.csdn.net/chenruichuan/[/url]
注:为了看的更清楚,版主修改了文本。
 楼主| 发表于 2008-7-13 23:21:25 | 显示全部楼层
接收到4字节长度以后,并没有判断是否大于BUFFER_SIZE,这可能导致缓冲区溢出。

另外,recv返回值不为4时直接返回-1,是比较草率的做法,可能在局域网测试时效果比较好,但无法保证其它网络环境中一样能很好地工作。

int Request_Handler::handle_input(ACE_HANDLE fd)
{
char length[4] = {0};
if(this->peer().recv_n(length, 4) == 4)
{
size_t msg_len = 0;
for(int i = 0; i < 4; i++)
{
msg_len |= (size_t)length << (8 * i);
}

char msg[BUFFER_SIZE] = {0};
if(this->peer().recv_n(msg, msg_len) == msg_len)
{
ACE_Message_Block *mb = NULL;
ACE_NEW_RETURN(mb, ACE_Message_Block(msg_len, ACE_Message_Block::MB_DATA, 0, msg), -1);
mb->wr_ptr(msg_len);
task_mgr.putq(mb);
return 0;
}
}
return -1;
}
 楼主| 发表于 2008-7-13 23:22:06 | 显示全部楼层

可供测试、调试的代码-客户端

这个是采用采用C++的ACE库实现的一个通用的C/S架构通信程序(最终版) 此帖的整理,大家可以进行直接编译测试、调试。
代码其实有很多需要改进的地方,比如:收发不能用阻塞的函数。
可以复制下面的代码,打开一个console工程,贴进去编译,注意设置ACE的相关环境、库文件。
客户端:
// client.cpp : 定义控制台应用程序的入口点。
//
  1. #include "stdafx.h"
  2. //2. 客户端:应用程序将需要发送的若干消息放入一个消息队列,然后激活一个线程来发送所有消息到服务器端。
  3. //客户端代码如下:(共4个文件)
  4. //ACE_Client.cpp
  5. //#include "Client.h"
  6. //Constants.h
  7. #ifndef __CONSTANTS_H_
  8. #define __CONSTANTS_H_
  9. #include "ace/Time_Value.h"
  10. namespace ACE_Client
  11. {
  12. static const size_t BUFFER_SIZE = 4096; //数据缓冲区大小
  13. static const size_t SERVER_PORT_NUM = 10101; //服务器的通信端口号
  14. static const ACE_Time_Value TIME_INTERVAL(0, 1000000); //两次数据发送之间的时间间隔(0 s + 1000000 us = 1 s)
  15. }
  16. #endif
  17. //Client.h
  18. #ifndef __CLIENT_H_
  19. #define __CLIENT_H_
  20. #include "ace/Task.h"
  21. #include "ace/INET_Addr.h"
  22. #include "ace/Synch.h"
  23. namespace ACE_Client
  24. {
  25. class Client: public ACE_Task<ACE_NULL_SYNCH>
  26. {
  27. public:
  28.   Client(char *server);
  29.   virtual int svc(void);
  30.   char *put_task(char *msg_t, char *msg_s, size_t msg_len);
  31.   void send_tasks(void);
  32. private:
  33.   ACE_INET_Addr addr;
  34. };
  35. }
  36. #endif
  37. //Client.cpp
  38. #include "ace/OS.h"
  39. #include "ace/SOCK_Stream.h"
  40. #include "ace/SOCK_Connector.h"
  41. #include "ace/Message_Block.h"
  42. #include "ace/Thread_Manager.h"
  43. #include "ace/INET_Addr.h"
  44. //#include "Constants.h"
  45. //#include "Client.h"
  46. namespace ACE_Client
  47. {
  48. Client::Client(char *server)
  49. {
  50.   addr = ACE_INET_Addr(SERVER_PORT_NUM, server);
  51. }
  52. int Client::svc(void)
  53. {
  54.   ACE_SOCK_Stream stream;
  55.   ACE_SOCK_Connector connector;
  56.   if(connector.connect(stream, addr) < 0)
  57.   {
  58.    return -1;
  59.   }
  60.   else
  61.   {
  62.    while(1)
  63.    {
  64.     ACE_Message_Block *mb = NULL;
  65.     if(this->getq(mb) == -1)
  66.     {
  67.      break;
  68.     }
  69.     ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%t) Sending %s\n"), &(mb->rd_ptr()[4])));
  70.     stream.send_n(mb->rd_ptr(), mb->length());
  71.     mb->release();
  72.     ACE_OS::sleep(TIME_INTERVAL);
  73.    }
  74.   }
  75.   stream.close();
  76.   return 0;
  77. }
  78. char *Client::put_task(char *msg_t, char *msg_s, size_t msg_len)
  79. {
  80.   for(int i = 0; i < 4; i++)
  81.   {
  82.    msg_t[i] = (char)((msg_len >> (8 * i)) & 0xff);
  83.   }
  84.   ACE_OS::memcpy(&msg_t[4], msg_s, msg_len);
  85.   ACE_Message_Block *mb = NULL;
  86.   ACE_NEW_RETURN(mb, ACE_Message_Block(msg_len + 4, ACE_Message_Block::MB_DATA, 0, msg_t), 0);
  87.   mb->wr_ptr(msg_len + 4);
  88.   this->putq(mb);
  89.   return msg_t;
  90. }
  91. void Client::send_tasks(void)
  92. {
  93.   this->activate();
  94.   ACE_Thread_Manager::instance()->wait();
  95. }
  96. }
  97. using namespace ACE_Client;
  98. int ACE_TMAIN(int argc, ACE_TCHAR *argv[])
  99. {
  100. Client client("localhost"); //服务器的IP地址或者服务器名称
  101. for(int i = 0; i < 5; i++)
  102. {
  103.   char *task1_t; //无需修改
  104.   char *task2_t; //无需修改
  105.   char *task1 = "Is it a good day?"; //第1个task的数据
  106.   size_t task1_len = 18; //第1个task的数据长度
  107.   ACE_NEW_RETURN(task1_t, char[task1_len + 4], -1); //无需修改
  108.   client.put_task(task1_t, task1, task1_len); //无需修改
  109.   char *task2 = "Yeah, it really is."; //第2个task的数据
  110.   size_t task2_len = 20; //第2个task的数据长度
  111.   ACE_NEW_RETURN(task2_t, char[task2_len + 4], -1); //无需修改
  112.   client.put_task(task2_t, task2, task2_len); //无需修改
  113.   delete [] task1_t; //释放task1的内存
  114.   delete [] task2_t; //释放task2的内存  
  115.   client.send_tasks(); //将上面的task全部发到服务器
  116. }
  117. return 0;
  118. }
复制代码
 楼主| 发表于 2008-7-13 23:22:30 | 显示全部楼层

可供测试、调试的代码-服务器端

服务器端:和客户端一样做工程上的处理,console环境即可。
  1. // Task.cpp : 定义控制台应用程序的入口点。
  2. //
  3. #include "stdafx.h"
  4. #include "ace/SOCK_Acceptor.h"
  5. #include "ace/Acceptor.h"
  6. #include "ace/Thread_Manager.h"
  7. #include "ace/TP_Reactor.h"
  8. #include "ace/Reactor.h"
  9. #include "ace/INET_Addr.h"
  10. #include "ace/OS.h"
  11. //#include "Request_Handler.h"
  12. //#include "Server.h"
  13. //#include "Constants.h"
  14. //Constants.h
  15. #ifndef __CONSTANTS_H_
  16. #define __CONSTANTS_H_
  17. namespace ACE_Server
  18. {
  19. static const size_t SERVER_THREAD_POOL_SIZE = 5; //进行数据接收的线程池大小
  20. static const size_t TASK_THREAD_POOL_SIZE = 5; //进行数据处理的线程池大小
  21. static const size_t BUFFER_SIZE = 4096; //数据缓冲区大小
  22. static const size_t SERVER_PORT_NUM = 10101; //服务器的通信端口号
  23. }
  24. #endif
  25. //Task_Worker.h
  26. #ifndef __TASK_WORKER_H_
  27. #define __TASK_WORKER_H_
  28. #include "ace/Task.h"
  29. #include "ace/Synch.h"
  30. #include "ace/Message_Block.h"
  31. namespace ACE_Server
  32. {
  33. class Task_Worker: public ACE_Task<ACE_MT_SYNCH>
  34. {
  35. public:
  36.   virtual int svc(void);
  37. private:
  38.   void process_task(ACE_Message_Block *mb);
  39. };
  40. }
  41. #endif
  42. //Task_Worker.cpp
  43. #include "ace/OS.h"
  44. #include "ace/Message_Block.h"
  45. //#include "Task_Worker.h"
  46. namespace ACE_Server
  47. {
  48. int Task_Worker::svc(void)
  49. {
  50.   while(1)
  51.   {
  52.    ACE_Message_Block *mb = NULL;
  53.    if(this->getq(mb) == -1)
  54.    {
  55.     continue;
  56.    }
  57.    process_task(mb);
  58.   }
  59.   return 0;
  60. }
  61. void Task_Worker::process_task(ACE_Message_Block *mb)
  62. {
  63.   //进行数据处理,数据的起始地址为mb->rd_ptr(),长度为mb->length()
  64.   ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%t) Processing task: %s length %d\n"), mb->rd_ptr(), mb->length()));
  65.   ACE_OS::sleep(3); //模拟数据处理过程
  66.   mb->release();
  67. }
  68. }
  69. //Task_Manager.h
  70. #ifndef __TASK_MANAGER_H_
  71. #define __TASK_MANAGER_H_
  72. #include "ace/Task.h"
  73. #include "ace/Synch.h"
  74. namespace ACE_Server
  75. {
  76. class Task_Manager: public ACE_Task<ACE_MT_SYNCH>
  77. {
  78. public:
  79.   virtual int svc(void);
  80. };
  81. }
  82. #endif
  83. //Task_Manager.cpp
  84. #include "ace/Message_Block.h"
  85. //#include "Task_Manager.h"
  86. //#include "Task_Worker.h"
  87. //#include "Constants.h"
  88. namespace ACE_Server
  89. {
  90. int Task_Manager::svc(void)
  91. {
  92.   Task_Worker task_tp;
  93.   task_tp.activate(THR_NEW_LWP | THR_JOINABLE, TASK_THREAD_POOL_SIZE);
  94.   while(1)
  95.   {
  96.    ACE_Message_Block *mb = NULL;
  97.    if(this->getq(mb) < 0)
  98.    {
  99.     task_tp.msg_queue()->deactivate();
  100.     task_tp.wait();
  101.    }
  102.    //
  103.    task_tp.putq(mb);
  104.   }
  105.   return 0;
  106. }
  107. }
  108. //Server.h
  109. #ifndef __SERVER_H_
  110. #define __SERVER_H_
  111. #include "ace/Task.h"
  112. namespace ACE_Server
  113. {
  114. class Server: public ACE_Task_Base
  115. {
  116. public:
  117.   virtual int svc(void);
  118. };
  119. }
  120. #endif
  121. //Server.cpp
  122. #include "ace/Reactor.h"
  123. //#include "Server.h"
  124. namespace ACE_Server
  125. {
  126. int Server::svc(void)
  127. {
  128.   int result = ACE_Reactor::instance()->run_reactor_event_loop();
  129.   if(result == -1)
  130.    return -1;
  131.   return 0;
  132. }
  133. }
  134. //Request_Handler.h
  135. #ifndef __REQUEST_HANDLER_H_
  136. #define __REQUEST_HANDLER_H_
  137. #include "ace/Svc_Handler.h"
  138. #include "ace/SOCK_Stream.h"
  139. #include "ace/Synch.h"
  140. #include "ace/Thread_Manager.h"
  141. //#include "Task_Manager.h"
  142. namespace ACE_Server
  143. {
  144. class Request_Handler: public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_MT_SYNCH>
  145. {
  146. public:
  147.   Request_Handler(ACE_Thread_Manager *thr_mgr = 0);
  148. protected:
  149.   virtual int handle_input(ACE_HANDLE fd = ACE_INVALID_HANDLE);
  150. private:
  151.   static Task_Manager task_mgr;
  152. };
  153. }
  154. #endif
  155. //Request_Handler.cpp
  156. #include "ace/OS.h"
  157. #include "ace/Message_Block.h"
  158. #include "ace/Thread_Manager.h"
  159. #include "ace/Svc_Handler.h"
  160. #include "ace/SOCK_Stream.h"
  161. #include "ace/Synch.h"
  162. #include "ace/Reactor.h"
  163. //#include "Request_Handler.h"
  164. //#include "Task_Manager.h"
  165. //#include "Constants.h"
  166. namespace ACE_Server
  167. {
  168. Task_Manager Request_Handler::task_mgr;
  169. Request_Handler::Request_Handler(ACE_Thread_Manager *thr_mgr): ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_MT_SYNCH> (thr_mgr)
  170. {
  171.   this->reactor(ACE_Reactor::instance());
  172.   task_mgr.activate();
  173. }
  174. int Request_Handler::handle_input(ACE_HANDLE fd)
  175. {
  176.   char length[4] = {0};
  177.   if(this->peer().recv_n(length, 4) == 4)
  178.   {
  179.    size_t msg_len = 0;
  180.    for(int i = 0; i < 4; i++)
  181.    {
  182.     msg_len |= (size_t)length << (8 * i);
  183.    }
  184.    char msg[BUFFER_SIZE] = {0};
  185.    if(this->peer().recv_n(msg, msg_len) == msg_len)
  186.    {
  187.     ACE_Message_Block *mb = NULL;
  188.     ACE_NEW_RETURN(mb, ACE_Message_Block(msg_len, ACE_Message_Block::MB_DATA, 0, msg), -1);
  189.     mb->wr_ptr(msg_len);
  190.     //
  191.     task_mgr.putq(mb);
  192.     return 0;
  193.    }
  194.   }
  195.   return -1;
  196. }
  197. }
  198. using namespace ACE_Server;
  199. int ACE_TMAIN(int argc, ACE_TCHAR *argv[])
  200. {
  201. ACE_TP_Reactor tp_reactor;
  202. ACE_Reactor reactor(&tp_reactor, 1);
  203. ACE_Reactor::instance(&reactor, 1);
  204. ACE_Acceptor<Request_Handler, ACE_SOCK_ACCEPTOR> acceptor;
  205. ACE_INET_Addr addr(SERVER_PORT_NUM);
  206. if(acceptor.open(addr) == -1)
  207.   return -1;
  208. Server server_tp;
  209. server_tp.activate(THR_NEW_LWP | THR_JOINABLE, SERVER_THREAD_POOL_SIZE);
  210. ACE_Thread_Manager::instance()->wait();
  211. return 0;
  212. }
复制代码
 楼主| 发表于 2008-7-13 23:23:18 | 显示全部楼层
我用原始的代码,  将客户端for(int i=0;i<5;i++)==>改为for(;;)

运行多个客户程序,就会出现这个问题, winston你可以试试,

你发的最终版的代码你改动哪儿了?

用你第二次发的代码测试还是会出现同样的问题啊,代码就这么点,怎么就找不出问题在哪儿呢?
 楼主| 发表于 2008-7-13 23:23:27 | 显示全部楼层
发现 static const size_t BUFFER_SIZE = 4096; //数据缓冲区大小

定义了数据缓冲区的大小, 而数据处理过程

void Task_Worker::process_task(ACE_Message_Block *mb)
{
  //进行数据处理,数据的起始地址为mb->rd_ptr(),长度为mb->length()
  ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%t) Processing task: %s length %d\n"), mb->rd_ptr(), mb->length()));
  ACE_OS::sleep(3); //模拟数据处理过程

  mb->release();
}

是不是太慢了,导致数据缓冲区溢出==〉内存出错==〉出现上面测试(for(;;))的问题

在测试出现问题的情况下,更改一下 ACE_OS::sleep(0.1); //模拟数据处理过程 ==〉问题解决了

或者增大数据缓冲区BUFFER_SIZE 应该也能解决问题吧
 楼主| 发表于 2008-7-13 23:23:37 | 显示全部楼层
我发现了问题所在
int Request_Handler::handle_input(ACE_HANDLE fd)方法中,当接收到具体数据后,生成了一个ACE_Message_Block对象,但是这个对象并不拥有指向数据的内存,也就是说数据指向的内存属于一个栈.当有大量客户端时,这个内存被重新初始化,所以总是"烫烫".
将ACE_NEW_RETURN(mb, ACE_Message_Block(msg_len, ACE_Message_Block::MB_DATA, 0, msg), -1);
改为ACE_NEW_RETURN(mb, ACE_Message_Block(msg_len, ACE_Message_Block::MB_DATA, 0, NULL), -1);
mb->copy(msg, msg_len);
问题就不再存在了.
进行这个试验时,将客户端程序中发送数据后延时的语句去掉(Client.cpp)//ACE_OS::sleep(TIME_INTERVAL);
 楼主| 发表于 2008-7-13 23:23:49 | 显示全部楼层
1. 服务器端:一个采用领导者/跟随者模型的线程池不断地接受从多个客户端发来的消息,并放入一个消息队列,然后又有一个采用半同步/半异步模型的线程池不断地从这个消息队列中取出消息进行处理。

========================================================================

是否对于这两个模式的应用场景有偏差呢,对于这样一个任务,一般是选择其中一个,或者你可以改进一下模型,取两个模型之长,但是现在是说把两个模型加在一起。。。。。。有这个必要吗
 楼主| 发表于 2008-7-13 23:24:10 | 显示全部楼层
原来那个for循环是解出数据的长度用的,你把它改成无限循环了,肯定出问题。。。
发表于 2012-7-9 16:43:54 | 显示全部楼层
收不到4个字节,理论上完全可能,  要先暂存下来
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-5-18 19:34 , Processed in 0.042462 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表