Windows下用gSOAP開發webservice程序

1、介紹

gSOAP編譯工具提供了一個SOAP/XML 關於C/C++ 語言的實現,從而讓C/C++語言開發web服務或客戶端程序的工作變得輕鬆了很多。gSOAP利用編譯器技術提供了一組透明化的SOAP API,並將與開發無關的SOAP實現細節相關的內容對用戶隱藏起來。gSOAP的編譯器能夠自動的將用戶定義的本地化的C或C++數據類型轉變爲符合XML語法的數據結構,反之亦然。

gSOAP包含一個WSDL生成器,用它來爲你的web服務生成web服務的解釋。gSOAP的解釋器及導入器可以使用戶不需要分析web服務的細節就可以實現一個客戶端或服務端程序。

官網地址:http://www.cs.fsu.edu/~engelen/soap.html

下載地址:http://sourceforge.net/projects/gsoap2/

2、開發過程(以經典的calc爲例)

第一步:下載gSOAP Toolkit,在gsoap\bin\win32目錄可以看到兩個應用:soapcpp2.exe和wsdl2h.exe;

第二步:生成客戶端和服務器端框架

需使用gSOAP生成客戶端和服務器端代碼框架。我們有兩種做法:

編寫WSDL,使用wsdl2h生成頭文件,再soapcpp2生成框架代碼;
編寫頭文件,使用soapcpp2生成框架代碼;
方法1比較通用,可方便使用其他語言開發,但是編寫wsdl語法複雜;方法2比較簡單,但不能與其他語言通用。
我個人會選擇第2個方法,效率第一!當然,如果已經從其他地方得到了wsdl文件,就用第1中方法。

方法2可參考:http://blog.csdn.net/kisaa133/article/details/7729856

下面來說方法1:
用wsdl2h生成頭文件過程如下:
使用的wsdl爲:http://www.genivia.com/calc.wsdl
將 wsdl2h.exe;soapcpp2.exe;typemap.dat;calc.wsdl 拷貝到你自己的工作目錄下,將wsdl文件也保存爲Calculator.wsdl,在cmd中,將目錄切換到工作目錄,執行 wsdl2h.exe -p calc.wsdl,將生成calc.h

calc.wsdl 文件如下

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="calc"
 targetNamespace="http://websrv.cs.fsu.edu/~engelen/calc.wsdl"
 xmlns:tns="http://websrv.cs.fsu.edu/~engelen/calc.wsdl"
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:ns="urn:calc"
 xmlns:SOAP="http://schemas.xmlsoap.org/wsdl/soap/"
 xmlns:MIME="http://schemas.xmlsoap.org/wsdl/mime/"
 xmlns:DIME="http://schemas.xmlsoap.org/ws/2002/04/dime/wsdl/"
 xmlns:WSDL="http://schemas.xmlsoap.org/wsdl/"
 xmlns="http://schemas.xmlsoap.org/wsdl/">

<types>

 <schema targetNamespace="urn:calc"
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:ns="urn:calc"
  xmlns="http://www.w3.org/2001/XMLSchema"
  elementFormDefault="unqualified"
  attributeFormDefault="unqualified">
  <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
 </schema>

</types>

<message name="addRequest">
 <part name="a" type="xsd:double"/>
 <part name="b" type="xsd:double"/>
</message>

<message name="addResponse">
 <part name="result" type="xsd:double"/>
</message>

<message name="subRequest">
 <part name="a" type="xsd:double"/>
 <part name="b" type="xsd:double"/>
</message>

<message name="subResponse">
 <part name="result" type="xsd:double"/>
</message>

<message name="mulRequest">
 <part name="a" type="xsd:double"/>
 <part name="b" type="xsd:double"/>
</message>

<message name="mulResponse">
 <part name="result" type="xsd:double"/>
</message>

<message name="divRequest">
 <part name="a" type="xsd:double"/>
 <part name="b" type="xsd:double"/>
</message>

<message name="divResponse">
 <part name="result" type="xsd:double"/>
</message>

<message name="powRequest">
 <part name="a" type="xsd:double"/>
 <part name="b" type="xsd:double"/>
</message>

<message name="powResponse">
 <part name="result" type="xsd:double"/>
</message>

<portType name="calcPortType">
 <operation name="add">
  <documentation>Service definition of function ns__add</documentation>
  <input message="tns:addRequest"/>
  <output message="tns:addResponse"/>
 </operation>
 <operation name="sub">
  <documentation>Service definition of function ns__sub</documentation>
  <input message="tns:subRequest"/>
  <output message="tns:subResponse"/>
 </operation>
 <operation name="mul">
  <documentation>Service definition of function ns__mul</documentation>
  <input message="tns:mulRequest"/>
  <output message="tns:mulResponse"/>
 </operation>
 <operation name="div">
  <documentation>Service definition of function ns__div</documentation>
  <input message="tns:divRequest"/>
  <output message="tns:divResponse"/>
 </operation>
 <operation name="pow">
  <documentation>Service definition of function ns__pow</documentation>
  <input message="tns:powRequest"/>
  <output message="tns:powResponse"/>
 </operation>
</portType>

<binding name="calc" type="tns:calcPortType">
 <SOAP:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
 <operation name="add">
  <SOAP:operation style="rpc" soapAction=""/>
  <input>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </input>
  <output>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </output>
 </operation>
 <operation name="sub">
  <SOAP:operation style="rpc" soapAction=""/>
  <input>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </input>
  <output>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </output>
 </operation>
 <operation name="mul">
  <SOAP:operation style="rpc" soapAction=""/>
  <input>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </input>
  <output>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </output>
 </operation>
 <operation name="div">
  <SOAP:operation style="rpc" soapAction=""/>
  <input>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </input>
  <output>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </output>
 </operation>
 <operation name="pow">
  <SOAP:operation style="rpc" soapAction=""/>
  <input>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </input>
  <output>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </output>
 </operation>
</binding>

<service name="calc">
 <documentation>gSOAP 2.7.9k generated service definition</documentation>
 <port name="calc" binding="tns:calc">
  <SOAP:address location="http://websrv.cs.fsu.edu/~engelen/calcserver.cgi"/>
 </port>
</service>

</definitions>

開始貼代碼(calc.h): 我生成的 *.h文件和下面的不一樣,看上去可能是gsoap的版本升級造成的。或者是生產了c++的代碼

wsdl2h常用選項

-o 文件名,指定輸出頭文件

-n 名空間前綴 代替默認的ns

-c 產生純C代碼,否則是C++代碼

-s 不要使用STL代碼

-t 文件名,指定type map文件,默認爲typemap.dat

-e 禁止爲enum成員加上名空間前綴

 

 

//gsoap ns service name:   calc
//gsoap ns  service port:  http://localhost/calc.wsdl
//gsoap ns service location:   http://localhost
//gsoap ns service executable: calc.cgi
//gsoap ns service encoding:   encoded
//gsoap ns service type:   calcPortType
 
 
//gsoap ns schema namespace: urn:add
 
//gsoap ns service method-documentation: add Sums two values
 
int ns__add(double a, double b, double *result);
 
//gsoap ns service method-documentation: sub Subtracts two values
 
int ns__sub(double a, double b, double *result);
 
//gsoap ns service method-documentation: mul Multiplies two values
 
int ns__mul(double a, double b, double *result);
 
//gsoap ns service method-documentation: div Divides two values
 
int ns__div(double a, double b, double *result);
 
//gsoap ns service method-documentation: pow Raises a to b
int ns__pow(double a, double b, double *result);


 

生成源文件:
 soapcpp2 頭文件
常用選項
-C 僅生成客戶端代碼
-S 僅生成服務器端代碼
-L 不要產生soapClientLib.c和soapServerLib.c文件
-c 產生純C代碼,否則是C++代碼(與頭文件有關)
-I 指定import路徑(見上文)
-x 不要產生XML示例文件
-i 生成C++包裝,客戶端爲xxxxProxy.h(.cpp),服務器端爲xxxxService.h(.cpp)。
在cmd命令行下進入工程目錄,執行: 
soapcpp2  -L -w -x -I D:\study\gSOAP\code\gsoap\import calc.h
即生成一堆文件,包括客戶端和服務端框架代碼。

第三步:編寫服務端程序

#include "soapH.h"
#include "calc.nsmap"
#include "stdsoap2.h"
#include <stdio.h>
#include <stdlib.h>
 
int main(int argc, char **argv)
{ 
    SOAP_SOCKET m, s; /* master and slave sockets */
    struct soap soap;
    soap_init(&soap);
 
    if (argc < 2)
        soap_serve(&soap);   /* serve as CGI application */
    else{ 
        m = soap_bind(&soap, NULL, atoi(argv[1]), 100);
 
        if (!soap_valid_socket(m)){ 
            soap_print_fault(&soap, stderr);
            exit(-1);
        }
 
        fprintf(stderr, "Socket connection successful: master socket = %d\n", m);
 
        for ( ; ; ){
            s = soap_accept(&soap);
            fprintf(stderr, "Socket connection successful: slave socket = %d\n", s);
 
            if (!soap_valid_socket(s)){ 
                soap_print_fault(&soap, stderr);
                exit(-1);
            }
 
            soap_serve(&soap);
            soap_end(&soap);
        }
    }
 
    return 0;
}
 
int ns__add(struct soap *soap, double a, double b, double *result)
{ 
    *result = a + b;
    return SOAP_OK;
}
 
int ns__sub(struct soap *soap, double a, double b, double *result)
{ 
    *result = a - b;
    return SOAP_OK;
}
 
int ns__mul(struct soap *soap, double a, double b, double *result)
{
    *result = a * b;
    return SOAP_OK;
}
 
int ns__div(struct soap *soap, double a, double b, double *result)
{ 
    if (b)
        *result = a / b;
    else{ 
        char *s = (char*)soap_malloc(soap, 1024);
        sprintf(s, "<error xmlns=\"http://tempuri.org/\">Can't divide %f by %f</error>", a, b);
        return soap_sender_fault(soap, "Division by zero", s);
    }
 
    return SOAP_OK;
}
 
int ns__pow(struct soap *soap, double a, double b, double *result)
 
{ 
    *result = pow(a, b);
    if (soap_errno == EDOM) {   /* soap_errno is like errno, but compatible with Win32 */
        char *s = (char*)soap_malloc(soap, 1024);
        sprintf(s, "Can't take the power of %f to %f", a, b);
        sprintf(s, "<error xmlns=\"http://tempuri.org/\">Can't take power of %f to %f</error>", a, b);
        return soap_sender_fault(soap, "Power function domain error", s);
    }
 
    return SOAP_OK;
}

第四步:編寫客戶端程序

#include "soapH.h"
#include "calc.nsmap"
#include <stdio.h>
#include <stdlib.h>
#include "stdsoap2.h"
 
const char server[] = "http://localhost:4546";//"http://websrv.cs.fsu.edu/~engelen/calcserver.cgi";
/* = "http://localhost:8080"; to test against samples/webserver */
 
int main(int argc, char **argv)
{ 
    struct soap soap;
    double a, b, result;
 
    if (argc < 4){
        fprintf(stderr, "Usage: [add|sub|mul|div|pow] num num\n");
        exit(0);
    }
 
    soap_init1(&soap, SOAP_XML_INDENT);
    //soap_init(&soap);
    //printf("add(%f,%f) \n",argv[2],argv[3]);
 
    a = strtod(argv[2], NULL);
    b = strtod(argv[3], NULL);
 
    switch (*argv[1])
    { 
    case 'a':
        printf("add(%f,%f) \n",a,b);
        soap_call_ns__add(&soap, server, NULL, a, b, &result);
        break;
    case 's':
        soap_call_ns__sub(&soap, server, "", a, b, &result);
        break;
    case 'm':
        soap_call_ns__mul(&soap, server, "", a, b, &result);
        break;
    case 'd':
        soap_call_ns__div(&soap, server, "", a, b, &result);
        break;
    case 'p':
        soap_call_ns__pow(&soap, server, "", a, b, &result);
        break;
    default:
        fprintf(stderr, "Unknown command\n");
        exit(0);
    }
 
    if (soap.error){
        printf("abcd\n");
        soap_print_fault(&soap, stderr);
        exit(1);
    } else 
        printf("result = %f\n", result);
 
    soap_destroy(&soap);
    soap_end(&soap);
    soap_done(&soap);
 
    return 0;
}

--------------------- 
作者:河東酷神 
來源:CSDN 
原文:https://blog.csdn.net/qianqiuwanzi/article/details/24120455 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章