ACE多线程服务器

    ACE(Adaptive Communication Environment),它是一个面向对象的、跨平台的、开放源码的网络编程基础设施框架。

    ACE 是由加利福尼亚大学Irvine分校的Douglas C.Schmidt 博士主导开发的,是一种跨平台可编译的网络编程API,并随后在工业界中发展、完善,它将底层的不同系统的细节透明化,为开发者提供统一的接口,从而可在不同系统上相互移植,提高代码利用率。与传统的网络编程相比,它更加规范化,极力避免工业开发中人们常会出现的错误情况,从而提高了程序的可靠性和易用性,并且拥有较高的性能优势。

    读者可以从http://www.cs.wustl.edu/~schmidt/ACE.html进一步了解ACE和下载、安装。同时可以点击这里下载有关ACE的相关电子书籍。

    本文实现了ACE的一个简单多线程服务器,主要是通过多线程处理并发能力。源代码请点击这里下载

    跟传统的socket编程一样,我们也需要在while循环中监听端口,并分配线程进行处理,程序的头文件定义如下:

 1 #include "ace/SOCK_Stream.h"
 2 #include "ace/SOCK_Acceptor.h"
 3 
 4 class ACE_Server {
 5 public:
 6     int run_svc();
 7 
 8 protected:
 9     //thread entity pointer class
10     class Thread_Args{
11     public:
12         //the pointer of allocating the space of new thread
13         Thread_Args(ACE_Server *lsp) : ls(lsp){}
14         ACE_Server *ls;
15         ACE_SOCK_Stream peer;
16     };
17 
18     virtual int handle_connections();
19     virtual int handle_data(ACE_SOCK_Stream* arg = 0);
20     int block_recv(ACE_SOCK_Stream* peer, char* recv_buf, size_t len);
21     void ACE_Server::getTime(char* result);
22     void ACE_Server::getLocalIp(char* result);
23     void getCalc(int param, char* result, int count, char* re_buf);
24     static ACE_THR_FUNC_RETURN thread_run(void *arg);
25 
26 private:
27     ACE_SOCK_Acceptor acceptor;
28     ACE_INET_Addr server_addr;
29 
30     //request catch size
31     static const int MAX_BUF = 2048;
32     //response catch size
33     static const int MAX_RESULT = 64;
34     //network port
35     static const int port = 20120;
36 };

定义好数据结构后,就可以实现具体的逻辑实现了:

  1 #include "ACE_Server.h"
  2 #include "ace/Thread_Manager.h"
  3 #include "ace/Auto_Ptr.h"
  4 
  5 int ACE_Server::run_svc(){
  6 
  7     printf("ACE_Server has been initialized.\n");
  8     if (server_addr.set(port) == -1)
  9     {
 10         printf("It is failed to set %d.\n", port);
 11         return -1;
 12     }
 13 
 14     printf("It is listening the port 20120...\n");
 15 
 16     if (acceptor.open(server_addr) == -1)
 17     {
 18         printf("It is failed to open the acceptor.\n");
 19         return -1;
 20     }
 21 
 22     for(;;){
 23         if(handle_connections() == -1) 
 24             return -1;
 25     }
 26     return acceptor.close();
 27 }
 28 
 29 ACE_THR_FUNC_RETURN ACE_Server::thread_run(void *arg)
 30 {
 31     
 32     auto_ptr<Thread_Args> thread_args(static_cast<Thread_Args *>(arg));
 33 
 34     if (thread_args->ls->handle_data(&(thread_args->peer)) == -1)
 35     {
 36         printf("It is failed to handle the data.\n");
 37     }
 38     thread_args->peer.close();
 39     return 0;
 40 }
 41 
 42 int ACE_Server::handle_connections(){
 43     auto_ptr<Thread_Args> thread_args (new Thread_Args(this));
 44     if (acceptor.accept(thread_args->peer) == -1)
 45     {
 46         printf("It is failed to get the input stream.\n");
 47         return -1;
 48     }
 49     //the core of allocating the sub thread
 50     if(ACE_Thread_Manager::instance()->spawn(
 51         ACE_Server::thread_run,//run the thread_run() upon every sub thread
 52         static_cast<void *> (thread_args.get()),
 53         THR_DETACHED | THR_SCOPE_SYSTEM) == -1)
 54     {
 55         return -1;
 56     }
 57     //It is not necessary to wait for all of sub_threads exiting.
 58     //ACE_Thread_Manager::instance()->wait();
 59     //It is necessary to release the pointer binding with thread_run().
 60     thread_args.release();
 61     return 0;
 62 }
 63 
 64 int ACE_Server::block_recv(ACE_SOCK_Stream* peer, char* recv_buf, size_t len)
 65 {
 66     int recvd_size = 0;
 67     if (recv_buf != NULL && len > 0)
 68     {
 69         if((recvd_size = peer->recv(recv_buf, len, 0)) == -1)
 70             printf("It is failed to receive data...\n");
 71     }
 72     return recvd_size;
 73 }
 74 
 75 void ACE_Server::getTime(char* result){
 76     if (result != NULL)
 77     {
 78         time_t t = time(0);  
 79         strftime(result, MAX_RESULT, "%Y-%m-%d\n", localtime(&t)); 
 80     }
 81 }
 82 
 83 void ACE_Server::getLocalIp(char* result){
 84     if (result != NULL){
 85         char szhostname[32]; 
 86         std::string addr = "";
 87         int size = 0;
 88         if(gethostname(szhostname,sizeof(szhostname))==0)   
 89         { 
 90             struct hostent* pHost; 
 91             pHost = gethostbyname(szhostname);  
 92             addr = inet_ntoa(*(struct in_addr*)pHost-> h_addr_list[0]);
 93             size = addr.length();
 94         }
 95 
 96         if (size < MAX_RESULT)
 97             strncpy(result, addr.c_str(), addr.length());
 98         else
 99             printf("Result is overflow.");
100         
101     }
102 }
103 
104 void ACE_Server::getCalc(int begin, char* result, int length, char* re_buf){
105     int sum = 0;
106     std::string value = "";
107     bool isValue = false;
108     if (result != NULL && re_buf != NULL && begin < length)
109     {
110         for (int i = begin; i < length && re_buf[i] != ' '; i++)
111         {
112             if (re_buf[i] == '=')
113             {
114                 isValue = true;
115                 continue;
116             }
117             else if (re_buf[i] == '&')
118             {
119                 isValue = false;
120                 sum += atoi(value.c_str());
121                 value = "";
122             }
123             if (isValue)
124             {
125                 value += re_buf[i];
126             }
127         }
128         sum += atoi(value.c_str());
129         value = "";
130     }
131     sprintf(result, "%d", sum);
132 }
133 
134 int ACE_Server::handle_data(ACE_SOCK_Stream * peer)
135 {
136     char* re_buf = new char[MAX_BUF];
137     char* result = new char[MAX_RESULT];
138     memset(re_buf, 0, MAX_BUF);
139     memset(result, 0, MAX_RESULT);
140 
141     int params = 0;
142     std::string querys = "";
143     
144     peer->disable(ACE_NONBLOCK);
145     peer->get_remote_addr(server_addr);
146 
147     printf("The client ip address is: %s\n", server_addr.get_host_addr());
148     printf("The client port is: %d\n", server_addr.get_port_number());
149 
150     int count = block_recv(peer, re_buf, MAX_BUF);
151     printf("The size of receiving data is %d\n", count);
152 
153     for(int i = 5; i < count && re_buf[i] != ' '; i++){
154         if (re_buf[i] == '?')
155         {
156             params = i + 1;
157             continue;
158         }
159         if (params == 0)
160         {
161             querys += re_buf[i];
162         }
163     }
164     if (strcmp(querys.c_str(), "at") == 0)
165     {
166         getTime(result);
167     }
168     else if(strcmp(querys.c_str(), "ip") == 0)
169     {
170         getLocalIp(result);
171     }
172     else if(strcmp(querys.c_str(), "calc") == 0)
173     {
174         getCalc(params, result, count, re_buf);
175     }
176     else if(strcmp(querys.c_str(), "json") == 0)
177     {
178         iovec iov[2];    
179         iov[0].iov_base = (char*)"HTTP/1.1 200 OK\n";    
180         iov[0].iov_len = strlen("HTTP/1.1 200 OK\n");
181 
182         std::string json = "[{\"title\":\"flowers\",\"desc\":\"the beautiful flowers.\"}]";
183         memcpy(result, (char*)json.c_str(), json.length()+1);
184         iov[1].iov_base = (char*)json.c_str();
185         iov[1].iov_len = json.length();
186 
187         if (peer->sendv_n(iov, 2) == -1)
188         {        
189             printf("It is failed to response 200 error.\n");    
190             return -1;
191         }
192         if (peer->send_n(result, MAX_RESULT) == -1)
193         {
194             printf("It is failed to send the result.\n");
195         }
196     }
197     else{
198         iovec iov[1];    
199         iov[0].iov_base = (char*)"HTTP/1.1 404\n";    
200         iov[0].iov_len = strlen("HTTP/1.1 404\n");
201         if (peer->sendv_n(iov, 1) == -1)    
202         {        
203             printf("It is failed to response 404 error.\n");    
204             return -1;
205         }
206         printf("The wrong query:: %s\n", re_buf);
207     }
208     printf(result);
209     printf("\n-----------------------------------------------\n");
210     if (peer->send_n(result, MAX_RESULT) == -1)
211     {
212         printf("It is failed to send the result.\n");
213     }
214 
215     delete [] re_buf;
216     delete [] result;
217     re_buf = nullptr;
218     result = nullptr;
219 
220     return 0;
221 }
222 
223 int main(int argc, char *argv[]){
224     ACE_Server server;
225     if(server.run_svc() == -1)
226         printf("It is failed to run the ACE_Server.\n");
227     return 0;
228 }

程序运行比较简单,只要在地址栏中输入端口号+关键词即可。
如获得客户端ip地址:

服务器获得如下结果:

小结:

ACE目前在工业界运用广泛,本文只是对ACE的多线程使用的一个简单实现,更多功能仍需探索和学习。

以后如有更多关于ACE的个人理解,会积极和大家分享。

转载于:https://www.cnblogs.com/michaelGD/archive/2012/11/30/2796783.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值