zoukankan      html  css  js  c++  java
  • ACE+gSOAP实现高性能WebService Server(C/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:

    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. typedef 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.   
    17. struct ns2__makeCardNotifyRspBean  
    18. {  
    19.     xsd__int result; //结果  
    20.     xsd__string error_desc; //错误描述  
    21. };  
    22.   
    23. //卡数据生成结果通知接口  
    24. 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、编写批处理文件:

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

     

    4、编写业务实现代码:

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

     

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

    1. #include <ace/OS.h>  
    2.   
    3. #include "stdsoap2.h"  
    4. #include "soapH.h"  
    5.   
    6. #include "Global_Define.h"  
    7. #include "ffcs_logger.h"  
    8.   
    9. /************************************************************************/  
    10. /* 全局变量                                                             */  
    11.   
    12. Logger g_logger;  
    13. GlobalValue g_val;  
    14.   
    15. /************************************************************************/  
    16.   
    17. static void * pthr_soap_server_process(void * arg);  
    18. static void * pthr_soap_server_process_task(void * arg);  
    19.   
    20. int ACE_TMAIN(int argc, ACE_TCHAR* argv[])  
    21. {  
    22.     g_val.g_sys_run = 1;  
    23.   
    24.     /*初始化日志系统*/  
    25.     g_logger.load_config(CONFIG_FILE);  
    26.     g_logger.open_logger();  
    27.   
    28.     /*加载配置参数*/  
    29.     if (g_val.load_config(CONFIG_FILE) == -1)   
    30.     {  
    31.         g_val.g_sys_run = 0;  
    32.         g_logger.error("Load config file [%s] fail!/n", CONFIG_FILE);  
    33.   
    34.         ACE_OS::exit();  
    35.         return 0;  
    36.     }  
    37.   
    38.     /*启动SOAP服务端,方式一*/  
    39.     /* 
    40.     if (ACE_Thread_Manager::instance()->spawn_n(1, 
    41.                                                 (ACE_THR_FUNC)pthr_soap_server_process,//Execute task one 
    42.                                                 NULL, //arguments 
    43.                                                 THR_NEW_LWP | THR_DETACHED, //New Light Weight Process 
    44.                                                 ACE_DEFAULT_THREAD_PRIORITY, 
    45.                                                 FFCS_SOAP_SERVER_GRPID)==-1) //Group ID 
    46.         g_logger.error("Failure to spawn /"pthr_soap_server_process/" of threads/n"); 
    47.     */  
    48.   
    49.     /*启动SOAP服务端,方式二*/  
    50.     if (ACE_Thread_Manager::instance()->spawn_n(1,  
    51.                                         (ACE_THR_FUNC)pthr_soap_server_process_task,//Execute task one  
    52.                                         NULL, //arguments  
    53.                                         THR_NEW_LWP | THR_DETACHED, //New Light Weight Process  
    54.                                         ACE_DEFAULT_THREAD_PRIORITY,  
    55.                                         FFCS_SOAP_SERVER_GRPID)==-1) //Group ID  
    56.         g_logger.error("Failure to spawn /"pthr_soap_server_process_task/" of threads/n");  
    57.   
    58.     while(g_val.g_sys_run == 1)   
    59.     {  
    60.         ACE_OS::sleep(1);  
    61.     }  
    62.   
    63.     return 0;  
    64. }  
    65.   
    66.   
    67. /*采用线程池的方式处理SOAP Client请求*/  
    68. static void * pthr_soap_server_process(void * arg)  
    69. {  
    70.     char cHost[] = "localhost"//服务器IP  
    71.     int iPort = 9908; //端口  
    72.   
    73.   
    74.   
    75.     struct soap soap;  
    76.     SOAP_SOCKET m, s;  
    77.     int i;  
    78.     struct timespec rqt;  
    79.   
    80.     struct soap *soap_thr[MAX_THR]; // 连接池运行时环境实例  
    81.     ACE_thread_t tid[MAX_THR]; //线程池标识  
    82.   
    83.     //初始化连接池运行时环境实例  
    84.     for (i = 0; i < MAX_THR; i++)   
    85.     {  
    86.         soap_thr[i] = NULL;  
    87.         tid[i] = 0;  
    88.     }  
    89.   
    90.     /*初始化服务*/  
    91.     soap_init(&soap);  
    92.     do   
    93.     {  
    94.         m = soap_bind(&soap, cHost, iPort, BACKLOG);  
    95.         if (!soap_valid_socket(m))   
    96.         {  
    97.             g_logger.error("Socket bind fail (%d);System retry after 10 seconds/n");  
    98.             ACE_OS::sleep(10);  
    99.             continue;  
    100.         }   
    101.         else   
    102.         {  
    103.             g_logger.debug("Socket %d connection successful %s on port %d/n", m, cHost, iPort);  
    104.             break;  
    105.         }  
    106.     } while (g_val.g_sys_run == 1);  
    107.   
    108.     /*处理请求*/  
    109.     while (g_val.g_sys_run == 1)  
    110.     {  
    111.         for (i = 0; i < MAX_THR; i++)   
    112.         {  
    113.             s = soap_accept(&soap);  
    114.             if (!soap_valid_socket(s))   
    115.             {  
    116.                 if (soap.errnum)   
    117.                 {  
    118.                     g_logger.error("SOAP异常:%d/n", soap.errnum);  
    119.                     continue// retry  
    120.                 }   
    121.                 else   
    122.                 {  
    123.                     g_logger.error("Server timed out/n");  
    124.                     break;  
    125.                 }  
    126.             }  
    127.   
    128.             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);  
    129.   
    130.             if (!soap_thr[i]) // 首次连接  
    131.             {  
    132.                 soap_thr[i] = soap_copy(&soap);  
    133.                 if (!soap_thr[i])   
    134.                 {  
    135.                     g_logger.error("系统异常/n");  
    136.                     break;  
    137.                 }  
    138.             }   
    139.             else // 循环连接,等待连接池释放资源  
    140.             {   
    141.                 ACE_Thread_Manager::instance()->join(tid[i]);  
    142.                 g_logger.debug("OLD Thread %d completed/n", i);  
    143.                 soap_destroy(soap_thr[i]);  
    144.                 soap_end(soap_thr[i]);  
    145.             }  
    146.   
    147.             soap_thr[i]->socket = s;  
    148.             //设置编码UTF-8  
    149.             soap_set_imode(soap_thr[i], SOAP_C_UTFSTRING);  
    150.   
    151.             /*处理SOAP请求*/  
    152.             tid[i] = ACE_Thread_Manager::instance()->spawn_n(1,  
    153.                                                             (ACE_THR_FUNC)soap_serve,//Execute task one  
    154.                                                             (void*)soap_thr[i], //arguments  
    155.                                                             THR_NEW_LWP | THR_JOINABLE, //New Light Weight Process  
    156.                                                             ACE_DEFAULT_THREAD_PRIORITY,  
    157.                                                             FFCS_SOAP_SERVER_GRPID);  
    158.               
    159.             if (tid[i] == -1) g_logger.error("Failure to spawn /"soap_serve/" of threads/n");  
    160.         }  
    161.   
    162.         rqt.tv_sec = 0;  
    163.         rqt.tv_nsec = 10000000;  
    164.         ACE_OS::nanosleep(&rqt);  
    165.     }  
    166.   
    167.     //释放资源  
    168.     for (i = 0; i < MAX_THR; i++)   
    169.     {  
    170.         if (soap_thr[i])   
    171.         {  
    172.             soap_free(soap_thr[i]); // == soap_done(soap_thr[i]); + free(soap_thr[i]);  
    173.         }  
    174.     }  
    175.   
    176.     soap_done(&soap);   
    177.   
    178.     return 0;  
    179. }  
    180.   
    181. /*采用线程池+消息队列的方式处理SOAP Client请求*/  
    182. static void * pthr_soap_server_process_task(void * arg)  
    183. {  
    184.     char cHost[] = "localhost"//服务器IP  
    185.     int iPort = 9908; //端口  
    186.   
    187.   
    188.   
    189.     struct soap soap;  
    190.     struct soap *pSoap;  
    191.     SOAP_SOCKET m, s;  
    192.     struct timespec rqt;  
    193.   
    194.     TaskSoapClient task_soap_client;  
    195.   
    196.     /*初始化服务*/  
    197.     soap_init(&soap);  
    198.     do   
    199.     {  
    200.         m = soap_bind(&soap, cHost, iPort, BACKLOG);  
    201.         if (!soap_valid_socket(m))   
    202.         {  
    203.             g_logger.error("Socket bind fail (%d);System retry after 10 seconds/n");  
    204.             ACE_OS::sleep(10);  
    205.             continue;  
    206.         }   
    207.         else   
    208.         {  
    209.             g_logger.debug("Socket %d connection successful %s on port %d/n", m, cHost, iPort);  
    210.             break;  
    211.         }  
    212.     } while (g_val.g_sys_run == 1);  
    213.   
    214.     /*创建消息处理ACE_Task*/  
    215.     task_soap_client.set_active(true);  
    216.     if (task_soap_client.activate(THR_NEW_LWP | THR_JOINABLE, TASK_SOAP_CLIENT_POOL_SIZE) == -1)  
    217.     {  
    218.         g_logger.error("TaskSoapClient activate failed/n");  
    219.         return 0;  
    220.     }  
    221.   
    222.     /*处理请求*/  
    223.     while (g_val.g_sys_run == 1)  
    224.     {  
    225.         s = soap_accept(&soap);  
    226.         if (!soap_valid_socket(s))   
    227.         {  
    228.             if (soap.errnum)   
    229.             {  
    230.                 g_logger.error("SOAP异常:%d/n", soap.errnum);  
    231.                 continue// retry  
    232.             }   
    233.             else   
    234.             {  
    235.                 g_logger.error("Server timed out/n");  
    236.                 break;  
    237.             }  
    238.         }  
    239.   
    240.         g_logger.debug("Accepts socket %d connection from IP %d.%d.%d.%d/n", s, (soap.ip >> 24)&0xFF, (soap.ip >> 16)&0xFF, (soap.ip >> 8)&0xFF, soap.ip&0xFF);  
    241.   
    242.         pSoap = soap_copy(&soap);  
    243.         if (!pSoap)   
    244.         {  
    245.             g_logger.error("系统异常/n");  
    246.             continue;  
    247.         }  
    248.         pSoap->socket = s;  
    249.         //设置编码UTF-8  
    250.         soap_set_imode(pSoap, SOAP_C_UTFSTRING);  
    251.   
    252.         /*放入队列*/  
    253.         task_soap_client.process_soap_client_requet((void *)pSoap);  
    254.   
    255.         rqt.tv_sec = 0;  
    256.         rqt.tv_nsec = 50000000;  
    257.         ACE_OS::nanosleep(&rqt);  
    258.     }  
    259.   
    260.     soap_done(&soap);   
    261.   
    262.     task_soap_client.set_active(false);  
    263.     task_soap_client.msg_queue()->close();  
    264.     task_soap_client.wait();  
    265.   
    266.     return 0;  
    267. }  

     

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

    1. /******************************************************************************************** 
    2. * huangjf 2009年12月 于福州 
    3. ********************************************************************************************/  
    4. #include <ace/OS.h>  
    5.   
    6. #include "Global_Define.h"  
    7. #include "ffcs_logger.h"  
    8. #include "ffcs_common.h"  
    9.   
    10. #include "stdsoap2.h"  
    11. #include "soapH.h"  
    12.   
    13. extern Logger g_logger;  
    14.   
    15.   
    16. /******************************************************************************************** 
    17. * WebService Client Requet 处理类 
    18. ********************************************************************************************/  
    19.   
    20. class TaskSoapClient: public ACE_Task<ACE_MT_SYNCH>  
    21. {  
    22. public:  
    23.     TaskSoapClient() : active_(false)  
    24.     {  
    25.         this->active_ = false;  
    26.         this->msg_queue()->high_water_mark(SOAP_HIGHT_MARK);  
    27.         ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) TaskSoapClient start/n")));  
    28.     }  
    29.   
    30.     virtual ~TaskSoapClient()  
    31.     {  
    32.         this->active_ = false;  
    33.         this->msg_queue()->close();  
    34.         ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) TaskSoapClient stop/n")));  
    35.     }  
    36.   
    37.     virtual int svc(void);  
    38.   
    39.     bool get_active();  
    40.     void set_active(bool b);  
    41.   
    42.     int process_soap_client_requet(void *soap);  
    43. private:  
    44.     bool active_;  
    45.   
    46.     void process_soap(ACE_Message_Block *mb = NULL);  
    47. };  
    48.   
    49.   
    50. //处理接收队列  
    51. int TaskSoapClient::svc(void)  
    52. {  
    53.     g_logger.debug("TaskSoapClient::svc() start/n");  
    54.   
    55.     while (this->active_==true)  
    56.     {  
    57.         ACE_Message_Block *mb = NULL;  
    58.         if (this->getq(mb) == -1)  
    59.         {  
    60.             /*g_logger.error("取接收队列数据失败/n");*/  
    61.             continue;  
    62.         }  
    63.   
    64.         process_soap(mb);  
    65.     }  
    66.   
    67.     g_logger.debug("TaskSoapClient::svc() stop/n");  
    68.     return 0;  
    69. }  
    70.   
    71. void TaskSoapClient::process_soap(ACE_Message_Block *mb)  
    72. {  
    73.     char * data = mb->rd_ptr();  
    74.     size_t data_size = mb->length();  
    75.   
    76.     /*g_logger.dump(data, data_size, 1);*/  
    77.   
    78.     /**************************************************************** 
    79.     * TODO 处理接收到的SOAP Client Request,数据的起始地址为data,长度为data_size 
    80.     *****************************************************************/  
    81.   
    82.     struct soap * pSoap = NULL;   
    83.   
    84.     try  
    85.     {  
    86.         ACE_OS::memcpy(&pSoap, data, MIN(data_size, sizeof(void *)));  
    87.     }  
    88.     catch (...)  
    89.     {  
    90.         g_logger.error("struct soap * 转换异常/n");  
    91.         return;  
    92.     }  
    93.   
    94.     if (pSoap)  
    95.     {  
    96.         if (!soap_valid_socket(pSoap->socket))   
    97.         {  
    98.             if (pSoap->errnum)   
    99.             {  
    100.                 g_logger.error("SOAP异常:%d/n", pSoap->errnum);  
    101.             }   
    102.             else   
    103.             {  
    104.                 g_logger.error("SOAP异常:??/n");  
    105.             }  
    106.   
    107.             soap_free(pSoap);/*销毁*/  
    108.             return;  
    109.         }  
    110.   
    111.         soap_serve(pSoap);   /*执行*/  
    112.   
    113.         soap_destroy(pSoap); /*释放*/  
    114.         soap_end(pSoap);     /*释放*/  
    115.   
    116.         soap_free(pSoap);    /*销毁*/  
    117.     }  
    118.   
    119.   
    120.   
    121.     //数据处理结束必需释放内存  
    122.     mb->release();  
    123. }  
    124.   
    125. /**********************************************************************************************************************************/  
    126.   
    127. void TaskSoapClient::set_active(bool b)  
    128. {  
    129.     this->active_ = b;  
    130. }  
    131.   
    132. bool TaskSoapClient::get_active()  
    133. {  
    134.     return this->active_;  
    135. }  
    136.   
    137. int TaskSoapClient::process_soap_client_requet(void *soap)  
    138. {  
    139.     int msg_len = sizeof(void *);  
    140.     ACE_Message_Block *mb = NULL;  
    141.   
    142.     ACE_NEW_RETURN(mb, ACE_Message_Block(msg_len+1), -1);  
    143.     ACE_OS::memcpy(mb->wr_ptr(), &soap, msg_len);  
    144.     mb->wr_ptr(msg_len);  
    145.   
    146.     if (this->putq(mb) == -1)  
    147.     {  
    148.         g_logger.error("SOAP Client Requet enqueue to TaskSoapClient failed/n");  
    149.         mb->release();  
    150.         return -1;  
    151.     }  
    152.   
    153.     return 1;  
    154. }  

     

    7、编译的时候不要忘记将%GSOAP_HOME%/gsoap/目录下的stdsoap2.cpp和stdsoap2.h引入工程;

  • 相关阅读:
    夺命雷公狗-----React---26--小案例之react经典案例todos(统计部分的完成)
    夺命雷公狗-----React---25--小案例之react经典案例todos(单选框的修改)
    夺命雷公狗-----React---24--小案例之react经典案例todos(单条任务的删除)
    夺命雷公狗-----React---23--小案例之react经典案例todos(完成添加任务)
    夺命雷公狗-----React---22--小案例之react经典案例todos(完成数据的遍历)
    react.js语法为了更好的兼容可以选以下这种方法配置即可
    无语啊,sublime给我弄乱玩,玩坏了,而且安装插件也安装不了
    夺命雷公狗-----React---21--小案例之心情留言板
    07-THREE.JS 各种形状的几何图形
    03-THREE.JS GUI使用
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13318711.html
Copyright © 2011-2022 走看看