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 "), mb->rd_ptr(), mb->length())); 213 ACE_OS::sleep(3); //模拟数据处理过程 214 mb->release(); 215 } 216 }
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 "), &(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 }