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
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!