微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ACE+gSOAP实现高性能WebService ServerC/C++

1、开发环境请参考《搭建ACE-5.7.4+VS2008开发环境》一文

 

2、gSOAP库,下载地址:http://gsoap2.sourceforge.net/,本文使用的版本是:gsoap_2.7.15,gSOAP的编程可以参考doc目录下的soapdoc2.pdf,官方文档写的非常详细。

让我们开始gSOAP编码旅程:

1、创建gsoap_server.h:

[cpp]  view plain copy
  1. //gsoap ns2 service namespace:  http://localhost:9908/ccm_mimport/services.wsdl  
  2. //gsoap ns2 service location:   http://localhost:9908/ccm_mimport/services  
  3.   
  4. typedef char * xsd__string; // encode char * value as the xsd:string schema type   
  5. int xsd__int; // encode xsd__int value as the xsd:int schema typ  
  6.   
  7. struct ns2__makeCardNotifyReqBean  
  8. {  
  9.     xsd__string id_makecard_order;  
  10.     xsd__int card_type;  
  11.     xsd__string file_name;  
  12.     xsd__string start_card_serial;  
  13.     xsd__string end_card_serial;  
  14.     xsd__int card_count;  
  15. };  
  16. struct ns2__makeCardNotifyRspBean  
  17.     xsd__int result; //结果  
  18.     xsd__string error_desc; //错误描述  
  19. //卡数据生成结果通知接口  
  20. int ns2__makeCardNotify(struct ns2__makeCardNotifyReqBean req, struct ns2__makeCardNotifyRspBean *rsp);  

注:头文件上面的注释用于配置服务访问地址,而非单纯的注释;详细配置说明可以参考官方文档

2、把%GSOAP_HOME%/gsoap/bin/win32目录配置到系统%Path%里,或者将目录下的soapcpp2.exe和wsdl2h.exe两个文件直接拷贝到gsoap_server.h所在目录;

3、编写批处理文件

copy

    echo off  
  1. del *.c *.h *.xml *.nsmap *.cpp  
  2. soapcpp2 -c -S gsoap_server.h  
  3. copy soapC.c ../soapC.cpp  
  4. copy soapServer.c ../soapServer.cpp  
  5. copy soapH.h ../soapH.h  
  6. copy soapStub.h ../soapStub.h  
  7. copy ns2.nsmap ../gsoap_server.nsmap  
  8. echo .  
  9. echo /******************************/  
  10. echo .  
  11. echo 生成的ns2.wsdl必须删除schemaLocation="http://schemas.xmlsoap.org/soap/encoding/"属性  
  12. pause  

4、编写业务实现代码

copy

    #include <ctype.h>  
  1. #include <string>  
  2. #include <ace/OS.h>  
  3. #include <ace/OS_NS_ctype.h>  
  4. #include <ace/OS_NS_string.h>  
  5. #include "Global_Define.h"  
  6. #include "ffcs_logger.h"  
  7. #include "stdsoap2.h"  
  8. #include "soapH.h"  
  9. #include "gsoap_server.nsmap"  
  10. extern Logger g_logger;  
  11. extern GlobalValue g_val;  
  12. /*----------------------------------------------------------------------- 
  13. * name:     卡数据生成结果通知接口 
  14. * input:    soap  -- gSOAP运行时环境实例 
  15. *           req  -- SOAP请求参数 
  16. * output:   rsp  -- SOAP应答参数 
  17. * return:   SOAP_OK  -- 成功 
  18. *           SOAP_ERR  -- 失败:将导致客户端接口调用异常,一般不使用  
  19. *-----------------------------------------------------------------------*/  
  20. SOAP_FMAC5 int SOAP_FMAC6 ns2__makeCardNotify(struct soaP* soap,153); background-color:inherit; font-weight:bold">struct ns2__makeCardNotifyRspBean *rsp)  
  21.     ACE_UINT64 ms_1, ms_2;  
  22.     ACE_OS::gettimeofday().msec(ms_1);  
  23.     g_logger.debug("*** SOAP请求开始 ***/n");  
  24.     if (req.id_makecard_order==NULL || req.file_name==NULL)  
  25.     {  
  26.         g_logger.error("格式无效/n");  
  27.         rsp->result = RET_FORMATERROR;  
  28.         rsp->error_desc = "";  
  29.         return SOAP_OK;  
  30.     }  
  31.     rsp->result = RET_SUCCESS;  
  32.     rsp->error_desc = "成功";  
  33.     ACE_OS::gettimeofday().msec(ms_2);  
  34.     g_logger.debug("*** SOAP请求结束,耗时 (%ld)ms ***/n", ms_2-ms_1);  
  35. return SOAP_OK;  
  36. }  

5、编写WebService服务端处理代码

copy

    #include <ace/OS.h>  
  1. /************************************************************************/  
  2. /* 全局变量                                                             */  
  3. Logger g_logger;  
  4. GlobalValue g_val;  
  5. static void * pthr_soap_server_process(void * arg);  
  6. void * pthr_soap_server_process_task(void * arg);  
  7. int ACE_TMAIN(int argc, ACE_TCHAR* argv[])  
  8. {  
  9.     g_val.g_sys_run = 1;  
  10.     /*初始化日志系统*/  
  11.     g_logger.load_config(CONfig_FILE);  
  12.     g_logger.open_logger();  
  13. /*加载配置参数*/  
  14. if (g_val.load_config(CONfig_FILE) == -1)   
  15.         g_val.g_sys_run = 0;  
  16.         g_logger.error("Load config file [%s] fail!/n", CONfig_FILE);  
  17.         ACE_OS::exit();  
  18.         return 0;  
  19.     }  
  20. /*启动SOAP服务端,方式一*/  
  21.     /* 
  22.     if (ACE_Thread_Manager::instance()->spawn_n(1, 
  23.                                                 (ACE_THR_FUNC)pthr_soap_server_process,//Execute task one 
  24.                                                 NULL, //arguments 
  25.                                                 THR_NEW_LWP | THR_DETACHED, //New Light Weight Process 
  26.                                                 ACE_DEFAULT_THREAD_PRIORITY,0); background-color:inherit">                                                FFCS_SOAP_SERVER_GRPID)==-1) //Group ID 
  27.         g_logger.error("Failure to spawn /"pthr_soap_server_process/" of threads/n"); 
  28.     */  
  29. /*启动SOAP服务端,方式二*/  
  30.     if (ACE_Thread_Manager::instance()->spawn_n(1,  
  31.                                         (ACE_THR_FUNC)pthr_soap_server_process_task,//Execute task one  
  32.                                         NULL, //arguments  
  33.                                         THR_NEW_LWP | THR_DETACHED,0); background-color:inherit">//New Light Weight Process  
  34.                                         ACE_DEFAULT_THREAD_PRIORITY,  
  35.                                         FFCS_SOAP_SERVER_GRPID)==-1) //Group ID  
  36.         g_logger.error("Failure to spawn /"pthr_soap_server_process_task/" of threads/n");  
  37. while(g_val.g_sys_run == 1)   
  38.     {  
  39.         ACE_OS::sleep(1);  
  40. }  
  41. /*采用线程池的方式处理SOAP Client请求*/  
  42. void * arg)  
  43.     char cHost[] = "localhost"//服务器IP  
  44.     int iPort = 9908; //端口  
  45. struct soap soap;  
  46.     SOAP_SOCKET m, s;  
  47. int i;  
  48. struct timespec rqt;  
  49. struct soap *soap_thr[MAX_THR]; // 连接池运行时环境实例  
  50.     ACE_thread_t tid[MAX_THR]; //线程池标识  
  51. //初始化连接池运行时环境实例  
  52. for (i = 0; i < MAX_THR; i++)   
  53.         soap_thr[i] = NULL;  
  54.         tid[i] = 0;  
  55. /*初始化服务*/  
  56.     soap_init(&soap);  
  57. do   
  58.         m = soap_bind(&soap, cHost, iPort, BACKLOG);  
  59. if (!soap_valid_socket(m))   
  60.         {  
  61.             g_logger.error("Socket bind fail (%d);System retry after 10 seconds/n");  
  62.             ACE_OS::sleep(10);  
  63.             continue;  
  64.         }   
  65. else   
  66.             g_logger.debug("Socket %d connection successful %s on port %d/n", m, iPort);  
  67.             break;  
  68.         }  
  69.     } while (g_val.g_sys_run == 1);  
  70. /*处理请求*/  
  71. while (g_val.g_sys_run == 1)  
  72. for (i = 0; i < MAX_THR; i++)   
  73.             s = soap_accept(&soap);  
  74. if (!soap_valid_socket(s))   
  75.             {  
  76.                 if (soap.errnum)   
  77.                 {  
  78.                     g_logger.error("SOAP异常:%d/n", soap.errnum);  
  79.                     continue// retry  
  80.                 }   
  81.                                  {  
  82.                     g_logger.error("Server timed out/n");  
  83.                                      }  
  84.             }  
  85.             g_logger.debug("Thread %d accepts socket %d connection from IP %d.%d.%d.%d/n", i, s, (soap.ip >> 24)&0xFF, (soap.ip >> 16)&0xFF, (soap.ip >> 8)&0xFF, soap.ip&0xFF);  
  86. if (!soap_thr[i]) // 首次连接  
  87.                 soap_thr[i] = soap_copy(&soap);  
  88. if (!soap_thr[i])   
  89.                     g_logger.error("系统异常/n");  
  90.             }   
  91. else // 循环连接,等待连接池释放资源  
  92.             {   
  93.                 ACE_Thread_Manager::instance()->join(tid[i]);  
  94.                 g_logger.debug("OLD Thread %d completed/n", i);  
  95.                 soap_destroy(soap_thr[i]);  
  96.                 soap_end(soap_thr[i]);  
  97.             }  
  98.             soap_thr[i]->socket = s;  
  99.             //设置编码UTF-8  
  100.             soap_set_imode(soap_thr[i], SOAP_C_UTFSTRING);  
  101.             /*处理SOAP请求*/  
  102.             tid[i] = ACE_Thread_Manager::instance()->spawn_n(1,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px">                                                             (ACE_THR_FUNC)soap_serve,248); line-height:18px">                                                             (void*)soap_thr[i],                                                              THR_NEW_LWP | THR_JOINABLE,248); line-height:18px">                                                             ACE_DEFAULT_THREAD_PRIORITY,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px">                                                             FFCS_SOAP_SERVER_GRPID);  
  103.               
  104. if (tid[i] == -1) g_logger.error("Failure to spawn /"soap_serve/" of threads/n");  
  105.         }  
  106.         rqt.tv_sec = 0;  
  107.         rqt.tv_nsec = 10000000;  
  108.         ACE_OS::nanosleep(&rqt);  
  109. //释放资源  
  110. if (soap_thr[i])   
  111.         {  
  112.             soap_free(soap_thr[i]); // == soap_done(soap_thr[i]); + free(soap_thr[i]);  
  113.     soap_done(&soap);   
  114. return 0;  
  115. }  
  116. /*采用线程池+消息队列的方式处理SOAP Client请求*/  
  117. struct soap *pSoap;  
  118.     SOAP_SOCKET m, s;  
  119.     TaskSoapClient task_soap_client;  
  120. /*创建消息处理ACE_Task*/  
  121.     task_soap_client.set_active(true);  
  122. if (task_soap_client.activate(THR_NEW_LWP | THR_JOINABLE, TASK_SOAP_CLIENT_POOL_SIZE) == -1)  
  123.         g_logger.error("TaskSoapClient activate Failed/n");  
  124.         s = soap_accept(&soap);  
  125.                 g_logger.error("SOAP异常:%d/n",248); line-height:18px">             {  
  126.                 g_logger.error("Server timed out/n");  
  127.         g_logger.debug("Accepts socket %d connection from IP %d.%d.%d.%d/n",248); line-height:18px">         pSoap = soap_copy(&soap);  
  128. if (!pSoap)   
  129.             g_logger.error("系统异常/n");  
  130. continue;  
  131.         pSoap->socket = s;  
  132.         //设置编码UTF-8  
  133.         soap_set_imode(pSoap, SOAP_C_UTFSTRING);  
  134.         /*放入队列*/  
  135.         task_soap_client.process_soap_client_requet((void *)pSoap);  
  136.         rqt.tv_sec = 0;  
  137.         rqt.tv_nsec = 50000000;  
  138.         ACE_OS::nanosleep(&rqt);  
  139.     task_soap_client.set_active(false);  
  140.     task_soap_client.msg_queue()->close();  
  141.     task_soap_client.wait();  
  142. }  

6、如果采用线程池+消息队列的方式处理SOAP Client请求,需要引入ACE_Task,并采用ACE_Message_Block实现对了操作:

copy

    /******************************************************************************************** 
  1. * huangjf 2009年12月 于福州 
  2. ********************************************************************************************/  
  3. #include "ffcs_common.h"  
  4. #include "stdsoap2.h"  
  5. #include "soapH.h"  
  6. /******************************************************************************************** 
  7. * WebService Client Requet 处理类 
  8. ********************************************************************************************/  
  9. class TaskSoapClient: public ACE_Task<ACE_MT_SYNCH>  
  10. public:  
  11.     TaskSoapClient() : active_(false)  
  12. this->active_ = false;  
  13. this->msg_queue()->high_water_mark(SOAP_HIGHT_MARK);  
  14.         ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) TaskSoapClient start/n")));  
  15. virtual ~TaskSoapClient()  
  16. false;  
  17. this->msg_queue()->close();  
  18.         ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) TaskSoapClient stop/n")));  
  19. virtual int svc(void);  
  20. bool get_active();  
  21. void set_active(bool b);  
  22. int process_soap_client_requet(void *soap);  
  23. private:  
  24. bool active_;  
  25. void process_soap(ACE_Message_Block *mb = NULL);  
  26. //处理接收队列  
  27. int TaskSoapClient::svc(void)  
  28.     g_logger.debug("TaskSoapClient::svc() start/n");  
  29. while (this->active_==true)  
  30.         ACE_Message_Block *mb = NULL;  
  31. if (this->getq(mb) == -1)  
  32. /*g_logger.error("取接收队列数据失败/n");*/  
  33.         process_soap(mb);  
  34.     g_logger.debug("TaskSoapClient::svc() stop/n");  
  35. void TaskSoapClient::process_soap(ACE_Message_Block *mb)  
  36. char * data = mb->rd_ptr();  
  37. size_t data_size = mb->length();  
  38. /*g_logger.dump(data, data_size, 1);*/  
  39. /**************************************************************** 
  40.     * Todo 处理接收到的SOAP Client Request,数据的起始地址为data,长度为data_size 
  41.     *****************************************************************/  
  42. struct soap * pSoap = NULL;   
  43. try  
  44.         ACE_OS::memcpy(&pSoap, data, MIN(data_size, sizeof(void *)));  
  45. catch (...)  
  46.         g_logger.error("struct soap * 转换异常/n");  
  47. return;  
  48. if (pSoap)  
  49. if (!soap_valid_socket(pSoap->socket))   
  50. if (pSoap->errnum)   
  51.             }   
  52. else   
  53.                 g_logger.error("SOAP异常:??/n");  
  54.             soap_free(pSoap);/*销毁*/  
  55. return;  
  56.         soap_serve(pSoap);   /*执行*/  
  57.         soap_destroy(pSoap); /*释放*/  
  58.         soap_end(pSoap);     /*释放*/  
  59.         soap_free(pSoap);    /*销毁*/  
  60. //数据处理结束必需释放内存  
  61.     mb->release();  
  62. /**********************************************************************************************************************************/  
  63. void TaskSoapClient::set_active(bool b)  
  64. this->active_ = b;  
  65. bool TaskSoapClient::get_active()  
  66. return this->active_;  
  67. int TaskSoapClient::process_soap_client_requet(void *soap)  
  68. int msg_len = void *);  
  69.     ACE_Message_Block *mb = NULL;  
  70.     ACE_NEW_RETURN(mb, ACE_Message_Block(msg_len+1), -1);  
  71.     ACE_OS::memcpy(mb->wr_ptr(), &soap, msg_len);  
  72.     mb->wr_ptr(msg_len);  
  73. this->putq(mb) == -1)  
  74.         g_logger.error("SOAP Client Requet enqueue to TaskSoapClient Failed/n");  
  75.         mb->release();  
  76. return -1;  
  77. return 1;  
  78. 7、编译的时候不要忘记将%GSOAP_HOME%/gsoap/目录下的stdsoap2.cpp和stdsoap2.h引入工程;

    版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

    相关推荐