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
版权声明:本文为博主原创文章,转载请附上博文链接!