DreamWorks

Never say Never。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

C++之ACE实现通用服务器的C/S架构通信程序

Posted on 2013-07-29 21:10  _Babyface  阅读(938)  评论(0编辑  收藏  举报

C++ACE实现通用的服务器C/S架构通信程序
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 ------------------------------------------------------------------------
 39 Server.h
 40 #ifndef __SERVER_H_
 41 #define __SERVER_H_
 42 #include "ace/Task.h"
 43 namespace ACE_Server
 44 {
 45 class Server: public ACE_Task_Base
 46 {
 47 public:
 48 virtual int svc(void);
 49 };
 50 }
 51 #endif
 52 ------------------------------------------------------------------------
 53 Server.cpp
 54 #include "ace/Reactor.h"
 55 #include "Server.h"
 56 namespace ACE_Server
 57 {
 58 int Server::svc(void)
 59 {
 60 int result = ACE_Reactor::instance()->run_reactor_event_loop();
 61 if(result == -1)
 62 return -1;
 63 return 0;
 64 }
 65 }
 66 ------------------------------------------------------------------------
 67 Request_Handler.h
 68 #ifndef __REQUEST_HANDLER_H_
 69 #define __REQUEST_HANDLER_H_
 70 #include "ace/Svc_Handler.h"
 71 #include "ace/SOCK_Stream.h"
 72 #include "ace/Synch.h"
 73 #include "ace/Thread_Manager.h"
 74 #include "Task_Manager.h"
 75 namespace ACE_Server
 76 {
 77 class Request_Handler: public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_MT_SYNCH>
 78 {
 79 public:
 80 Request_Handler(ACE_Thread_Manager *thr_mgr = 0);
 81 protected:
 82 virtual int handle_input(ACE_HANDLE fd = ACE_INVALID_HANDLE);
 83 private:
 84 static Task_Manager task_mgr;
 85 };
 86 }
 87 #endif
 88 ------------------------------------------------------------------------
 89 Request_Handler.cpp
 90 #include "ace/OS.h"
 91 #include "ace/Message_Block.h"
 92 #include "ace/Thread_Manager.h"
 93 #include "ace/Svc_Handler.h"
 94 #include "ace/SOCK_Stream.h"
 95 #include "ace/Synch.h"
 96 #include "ace/Reactor.h"
 97 #include "Request_Handler.h"
 98 #include "Task_Manager.h"
 99 #include "Constants.h"
100 namespace ACE_Server
101 {
102 Task_Manager Request_Handler::task_mgr;
103 Request_Handler::Request_Handler(ACE_Thread_Manager *thr_mgr): ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_MT_SYNCH> (thr_mgr)
104 {
105 this->reactor(ACE_Reactor::instance());
106 task_mgr.activate();
107 }
108 int Request_Handler::handle_input(ACE_HANDLE fd)
109 {
110 char length[4] = {0};
111 if(this->peer().recv_n(length, 4) == 4)
112 {
113 size_t msg_len = 0;
114 for(int i = 0; i < 4; i++)
115 {
116 msg_len |= (size_t)length[i] << (8 * i);
117 }
118 char msg[BUFFER_SIZE] = {0};
119 if(this->peer().recv_n(msg, msg_len) == msg_len)
120 {
121 ACE_Message_Block *mb = NULL;
122 ACE_NEW_RETURN(mb, ACE_Message_Block(msg_len, ACE_Message_Block::MB_DATA, 0, msg), -1);
123 mb->wr_ptr(msg_len);
124 task_mgr.putq(mb);
125 return 0;
126 }
127 }
128 return -1;
129 }
130 }
131 ------------------------------------------------------------------------
132 Task_Manager.h
133 #ifndef __TASK_MANAGER_H_
134 #define __TASK_MANAGER_H_
135 #include "ace/Task.h"
136 #include "ace/Synch.h"
137 namespace ACE_Server
138 {
139 class Task_Manager: public ACE_Task<ACE_MT_SYNCH>
140 {
141 public:
142 virtual int svc(void);
143 };
144 }
145 #endif
146 ------------------------------------------------------------------------
147 Task_Manager.cpp
148 #include "ace/Message_Block.h"
149 #include "Task_Manager.h"
150 #include "Task_Worker.h"
151 #include "Constants.h"
152 namespace ACE_Server
153 {
154 int Task_Manager::svc(void)
155 {
156 Task_Worker task_tp;
157 task_tp.activate(THR_NEW_LWP | THR_JOINABLE, TASK_THREAD_POOL_SIZE);
158 while(1)
159 {
160 ACE_Message_Block *mb = NULL;
161 if(this->getq(mb) < 0)
162 {
163 task_tp.msg_queue()->deactivate();
164 task_tp.wait();
165 }
166 task_tp.putq(mb);
167 }
168 return 0;
169 }
170 }
171 ------------------------------------------------------------------------
172 Task_Worker.h
173 #ifndef __TASK_WORKER_H_
174 #define __TASK_WORKER_H_
175 #include "ace/Task.h"
176 #include "ace/Synch.h"
177 #include "ace/Message_Block.h"
178 namespace ACE_Server
179 {
180 class Task_Worker: public ACE_Task<ACE_MT_SYNCH>
181 {
182 public:
183 virtual int svc(void);
184 private:
185 void process_task(ACE_Message_Block *mb);
186 };
187 }
188 #endif
189 ------------------------------------------------------------------------
190 Task_Worker.cpp
191 #include "ace/OS.h"
192 #include "ace/Message_Block.h"
193 #include "Task_Worker.h"
194 namespace ACE_Server
195 {
196 int Task_Worker::svc(void)
197 {
198 while(1)
199 {
200 ACE_Message_Block *mb = NULL;
201 if(this->getq(mb) == -1)
202 {
203 continue;
204 }
205 process_task(mb);
206 }
207 return 0;
208 }
209 void Task_Worker::process_task(ACE_Message_Block *mb)
210 {
211 //进行数据处理,数据的起始地址为mb->rd_ptr(),长度为mb->length()
212 ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%t) Processing task: %s length %d\n"), mb->rd_ptr(), mb->length()));
213 ACE_OS::sleep(3); //模拟数据处理过程
214 mb->release();
215 }
216 }
View Code

2. 客户端:应用程序将需要发送的若干消息放入一个消息队列,然后激活一个线程来发送所有消息到服务器端。

客户端代码如下:(共4个文件)

  1 //ACE_Client.cpp
  2 #include "Client.h"
  3 using namespace ACE_Client;
  4 int main(int argc, char *argv[])
  5 {
  6 Client client("localhost"); //服务器的IP地址或者服务器名称
  7 for(int i = 0; i < 5; i++)
  8 {
  9 char *task1 = "Is it a good day?"; //第1个task的数据
 10 size_t task1_len = 18; //第1个task的数据长度
 11 char *task1_t; //无需修改
 12 ACE_NEW_RETURN(task1_t, char[task1_len + 4], -1); //无需修改
 13 client.put_task(task1_t, task1, task1_len); //无需修改
 14 char *task2 = "Yeah, it really is."; //第2个task的数据
 15 size_t task2_len = 20; //第2个task的数据长度
 16 char *task2_t; //无需修改
 17 ACE_NEW_RETURN(task2_t, char[task2_len + 4], -1); //无需修改
 18 client.put_task(task2_t, task2, task2_len); //无需修改
 19 client.send_tasks(); //将上面的task全部发到服务器
 20 delete [] task1_t; //释放task1的内存
 21 delete [] task2_t; //释放task2的内存
 22 }
 23 return 0;
 24 }
 25 ------------------------------------------------------------------------
 26 Constants.h
 27 #ifndef __CONSTANTS_H_
 28 #define __CONSTANTS_H_
 29 #include "ace/Time_Value.h"
 30 namespace ACE_Client
 31 {
 32 static const size_t BUFFER_SIZE = 4096; //数据缓冲区大小
 33 static const size_t SERVER_PORT_NUM = 10101; //服务器的通信端口号
 34 static const ACE_Time_Value TIME_INTERVAL(0, 1000000); //两次数据发送之间的时间间隔(0 s + 1000000 us = 1 s)
 35 }
 36 #endif
 37 ------------------------------------------------------------------------
 38 Client.h
 39 #ifndef __CLIENT_H_
 40 #define __CLIENT_H_
 41 #include "ace/Task.h"
 42 #include "ace/INET_Addr.h"
 43 #include "ace/Synch.h"
 44 namespace ACE_Client
 45 {
 46 class Client: public ACE_Task<ACE_NULL_SYNCH>
 47 {
 48 public:
 49 Client(char *server);
 50 virtual int svc(void);
 51 char *put_task(char *msg_t, char *msg_s, size_t msg_len);
 52 void send_tasks(void);
 53 private:
 54 ACE_INET_Addr addr;
 55 };
 56 }
 57 #endif
 58 ------------------------------------------------------------------------
 59 Client.cpp
 60 #include "ace/OS.h"
 61 #include "ace/SOCK_Stream.h"
 62 #include "ace/SOCK_Connector.h"
 63 #include "ace/Message_Block.h"
 64 #include "ace/Thread_Manager.h"
 65 #include "ace/INET_Addr.h"
 66 #include "Constants.h"
 67 #include "Client.h"
 68 namespace ACE_Client
 69 {
 70 Client::Client(char *server)
 71 {
 72 addr = ACE_INET_Addr(SERVER_PORT_NUM, server);
 73 }
 74 int Client::svc(void)
 75 {
 76 ACE_SOCK_Stream stream;
 77 ACE_SOCK_Connector connector;
 78 if(connector.connect(stream, addr) < 0)
 79 {
 80 return -1;
 81 }
 82 else
 83 {
 84 while(1)
 85 {
 86 ACE_Message_Block *mb = NULL;
 87 if(this->getq(mb) == -1)
 88 {
 89 break;
 90 }
 91 ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%t) Sending %s\n"), &(mb->rd_ptr()[4])));
 92 stream.send_n(mb->rd_ptr(), mb->length());
 93 mb->release();
 94 ACE_OS::sleep(TIME_INTERVAL);
 95 }
 96 }
 97 stream.close();
 98 return 0;
 99 }
100 char *Client::put_task(char *msg_t, char *msg_s, size_t msg_len)
101 {
102 for(int i = 0; i < 4; i++)
103 {
104 msg_t[i] = (char)((msg_len >> (8 * i)) & 0xff);
105 }
106 ACE_OS::memcpy(&msg_t[4], msg_s, msg_len);
107 ACE_Message_Block *mb = NULL;
108 ACE_NEW_RETURN(mb, ACE_Message_Block(msg_len + 4, ACE_Message_Block::MB_DATA, 0, msg_t), 0);
109 mb->wr_ptr(msg_len + 4);
110 this->putq(mb);
111 return msg_t;
112 }
113 void Client::send_tasks(void)
114 {
115 this->activate();
116 ACE_Thread_Manager::instance()->wait();
117 }
118 }   
View Code