gSOAP 2.8.5 用户手册
1 简介
gSOAP工具基于编译器技术为C/C++提供自动的SOAP和XML数据绑定。(这句话很差理解,且向下看)。该工具使用自动生成代码以及先进的映射方法,简化了基于C/C++的SOAP/XML Web service和XML应用程序的开发。(有点靠谱了,能够理解成该工具能够帮助程序员完成协议底层的代码)。大多数Web services工具采用以WSDL/SOAP为中心的观点,而且提供一组API,使用这些API必须使用相应的类库来处理特定XML数据结构。这强迫用户去适应该程序逻辑才能使用这些类库,由于用户在使用该特定厂商的API时必须编写代码去填充XML和抽取XML数据。这每每致使一个脆弱的解决方案,几乎没有数据一致性、类型安全和XML验证的保证。(好了,损完别人了,下面开始自诩)。与其余工具不一样的是,gSOAP使用编译器技术为用户隐藏了WSDL、SOAP、特定XML的实现细节,同时自动提供XML有效性验证、内存管理和类型安全序列化,从而提供透明的解决方案。gSOAP工具可将原有的数据类型和用户自定义的数据类型映射成等价的XML数据类型,反之亦然。所以,经过一个简单的API获得了完美的SOAP互操做性,从而可以使用用户从WSDL/SOAP/XML的细节中解脱出来,集中精力处理应用程序逻辑。(主要仍是讲了gSOAP能够给用户,即程序员,提供协议透明,经过什么方式呢?经过自动生成的代码)
gSOAP工具支持传统的C/C++代码(以及留有C接口的其余编程语言)、嵌入式系统、那些和其余SOAP程序共享计算资源和信息的实时SOAP/XML应用程序之间的集成,能够跨平台,适用不一样的语言环境和穿透防火墙。(翻这段很累,还没翻好)
gSOAP工具经常使用C/C++实现XML数据绑定。这意味着程序本地数据结构可被自动地用XML编码,而不须要额外去编写转换代码。该工具还为了XML数据绑定生成XML模式,因此外部程序能够基于该模式使用XML数据。(不懂,且往下看)
1.1 准备工做
使用gSOAP工具构建Web services应用程序或实现自动化XML数据绑定,你须要具有以下条件:
- C或C++编译器
- 如想支持SSL(HTTPS)和压缩,你还须要安装OpenSSL、Zlib库.这些库适用于大多数平台,同时一般也是已经安装好的。
gSOAP是独立的软件,不须要安装第三方软件(除非你想使用OpenSSL或者你想从新构建soapcpp2工具,见下文)
从SourceForge获取的gSOAP包在gsoap/bin目录下有预构建的工具:(注:SourceForget是开源软件开发者进行开发管理的集中式场所,也是全球最大开源软件开发平台和仓库)
- wsdl2h :WSDL/模式导入和数据映射绑定工具。(注:该工具将wsdl转换为开发用的.h文件)
- soapcpp2 :存根/框架编译器和代码生成器。(注:该工具依据.h文件自动生成部分C/CPP语言代码)
这两个程序支持Windows、Linux和Mac OS 平台,详情参考README文件。
尽管gSOAP为不一样平台准备了二进制格式的工具,但他们生成的代码是等价的。这意味着生成的源代码能够移植到其余平台并进行本地化编译。
若是你没有该工具,或者你想从新构建,你须要:
- 一个C编译器和Bison(或Yacc)来构建soapcpp2。(注Bison和Yacc也是一种编译器)
- 一个C编译器和Flex(或Lex)来构建soapcpp2。
- 一个C++编译器来构建wsdl2h。
Bison和Flex是首选的。二者与gSOAP基于相同的开源标准发布的。
- Bison 可今后处得到: http://www.gnu.org/software/bison
- Flex 可今后处得到: http://flex.sourceforge.net
gSOAP引擎能够被构建成libgsoap.a和libgsoap++.a库,后者支持SSL。参照README.txt的指示能够看到如何经过gSOAP包里的autoconf和automake构建与平台无关的库。或者,你将引擎的源代码stdsoap2.c(或stdsoap2.cpp)直接编译并连接进大家工程里。(注:说明gSOAP提供两种使用方式 ,一种编译成动态连接库,或者直接将源代码编译进工程)
gSOAP包中,在samples目录下有不少例子。执行make命令能够构建这些例子程序。这些例子同时也是用来展现gSOAP不一样特性的。好比,在samples/mtom-streaming中,一个流式的MTOM附件服务端和客户端程序展现高效的文件传输;在samples/webservice中,SSL-secure网络服务端展现能够为Web流览器和Web服务调用生成不一样的内容。诸如此类,还有不少。
1.2 快速开始:开发一个Web Service客户端应用程序
经过高级XML模式分析器和代码生成器可实现XML数据绑定,这大大减小了构建Web Service程序的难度。wsdl2h工具导入一个或多个WSDL和XML模式能够生成C/C++头文件,该文件定义了Web Service操做以及C/C++数据类型。gsoapcpp2然手根据该头文件生成XML序列化的数据类型、客户端框架代码(soapClient.cpp)和服务端框架代码(soapServer.cpp)。
gSOAP编译器也能够生成WSDL定义文件,用来从头实现一个服务。这个闭环可使Web services开发基于WSDL文件或者基于C/C++头文件中的一系列选项,不须要用户去分析Web服务细节。
你只须要遵循一些步骤执行命令行或Makefile(使用MSVC++ IDE的话参照sample目录下的MSVC++例子)。例如,为了生成计算器Web应用代码,咱们经过命令行执行wsdl2h工具,从URL上的WSDL文件生成头文件,这里使用-o指定输出文件名:
wsdl2h -o calc.h http://www.genivia.com/calc.wsdl
(注:在浏览器中访问
http://www.genivia.com/calc.wsdl 能够得到一个wsdl文件,在该命令行中,用此wsdl文件名替换连接也是能够的)
这样就生成了描述服务操做定义及数据类型定义的头文件calc.h。接着能够经过soapcpp2将该头文件生成框架代码或XML序列化例程。calc.h头文件包含全部的说明,你可使用Doxygen(http://www.doxygen.org)来生成开发文档。
使用wsdl2h生成的服务定义头文件一样包含如何调用服务的信息。
在这个例子中,咱们开发一个基于C++的计算器服务。默认状况下,gSOAP假定咱们使用C++的STL。如不想使用STL,使用选项-s:
wsdl2h -s -o calc.h http://www.genivia.com/calc.wsdl
构建纯C程序,使用-c:
wsdl2h -c -o calc.h http://www.genivia.com/calc.wsdl
到如今为止,咱们尚未生成C/C++的存根。为了生成它,咱们使用soapcpp2编译器:
soapcpp2 -i -C -Iimport calc.h
选项-i指示咱们但愿获得C++代理和包含客户端(服务端)代码的对象。-C指示只生成客户端对象(默认状况下,gsoapcpp2同时生成客户端和服务端对象)。选项-I指示须要从import目录引入stlvector.h文件,以支持STL容器序列化,import目录也在gSOAP包中。
假定咱们开发一个C++计算器客户端:
wsdl2h -o calc.h http://www.genivia.com/calc.wsdl
soapcpp2 -i -C calc.h
(注:事实上执行第二行命令须要指定-I路径,以下所示:其中红色的文件是该步骤生成的)
./soapcpp2 -i -C -I/home/infor/renhc/gsoap/gsoap_2.8.5/gsoap-2.8/gsoap/import calc.h
[infor@s123 linux386]$ ls -ltr
total 3376
-rwxr-xr-x 1 infor app 2383149 Dec 6 11:46 wsdl2h
-rwxr-xr-x 1 infor app 818123 Dec 6 11:46 soapcpp2
-rw-r--r-- 1 infor app 5249 Dec 6 13:53 calc.wsdl
-rw-r--r-- 1 infor app 24316 Dec 6 14:42 calc.h-rw-r--r-- 1 infor app 7101 Dec 6 14:44 soapStub.h -rw-r--r-- 1 infor app 34463 Dec 6 14:44 soapH.h -rw-r--r-- 1 infor app 95689 Dec 6 14:44 soapC.cpp -rw-r--r-- 1 infor app 3573 Dec 6 14:44 soapcalcProxy.h -rw-r--r-- 1 infor app 12319 Dec 6 14:44 soapcalcProxy.cpp -rw-r--r-- 1 infor app 490 Dec 6 14:44 calc.sub.res.xml -rw-r--r-- 1 infor app 478 Dec 6 14:44 calc.sub.req.xml -rw-r--r-- 1 infor app 490 Dec 6 14:44 calc.pow.res.xml -rw-r--r-- 1 infor app 478 Dec 6 14:44 calc.pow.req.xml -rw-r--r-- 1 infor app 521 Dec 6 14:44 calc.nsmap -rw-r--r-- 1 infor app 490 Dec 6 14:44 calc.mul.res.xml -rw-r--r-- 1 infor app 478 Dec 6 14:44 calc.mul.req.xml -rw-r--r-- 1 infor app 490 Dec 6 14:44 calc.div.res.xml -rw-r--r-- 1 infor app 478 Dec 6 14:44 calc.div.req.xml -rw-r--r-- 1 infor app 490 Dec 6 14:44 calc.add.res.xml -rw-r--r-- 1 infor app 478 Dec 6 14:44 calc.add.req.xml
咱们使用生成的soapcalcProxy类和XML命名空间映射表calc.nsmap来访问Web服务。该soapcalcProxy类是调用服务的一个代理。
#include "soapcalcProxy.h"
#include "calc.nsmap"
main()
{
calcProxy service;
double result;
if (service.add(1.0, 2.0, result) == SOAP_OK)
std::cout << "The sum of 1.0 and 2.0 is " << result << std::endl;
else
service.soap_stream_fault(std::cerr);
}
接下来咱们编译并连接生成的soapC.cpp和soapcalcProxy.cpp,以及动态连接库-lgsoap++(若是你没有安装该库,能够将stdsoap2.cpp引入到你的代码)。(注:上面就构建完了基于C++的客户端)
假定咱们开发的是C语言客户端,那么咱们能够这样:
wsdl2h -c -o calc.h http://www.genivia.com/calc.wsdl
soapcpp2 -C calc.h
代码须要遵循C语言规范:
#include "soapH.h"
#include "calc.nsmap"
main()
{
struct soap *soap = soap_new();
double result;
if (soap_call_ns__add(soap, 1.0, 2.0, &result) == SOAP_OK)
printf("The sum of 1.0 and 2.0 is %lg\n", result);
else
soap_print_fault(soap, stderr);
soap_end(soap);
soap_free(soap);
}
这个计算器的例子是至关简单,此处只用来讲明开发过程。这与大型程序开发流程是类似的。更多的能够参考sample目录下的例子。
1.3 快速开始:开发Web 服务
开发服务端程序也很简单。这里咱们使用CGI,由于这是个简单的机制。(注:CGI英文全拼是Common Gateway Interface,即通用网关接口)。这不是首选的部署机制,由于CGI很是慢并且无国籍,咱们建议开发独立的gSOAP HTTP/HTTPS服务(参照本节最后部分注解)或者使用Apache组件,再或者IIS(在gSOAP包的gsoap/mod_gsoap目录下)。
假设咱们开发一个基于CGI的服务,该服务返回GMT时间。CGI能够很是简单的将服务发布到Web站点。
咱们以一个gSOAP头文件开始本例,currentTime.h包含服务的定义。若是咱们能获得WSDL文件,咱们可使用wsdl2h获得这样的头文件。若是没有WSDL,你可使用C/C++重头定义一个头文件,而后使用gSOAP工具生成源代码和WSDL。
咱们的currentTime服务只有一个输出参数,就是当前时间,在currentTime.h文件中定义以下:
// File: currentTime.h
//gsoap ns service name: currentTime
//gsoap ns service namespace: urn:currentTime
//gsoap ns service location: http://www.yourdomain.com/currentTime.cgi
int ns__currentTime(time_t& response);
注意,咱们关联一个XML命名空间前缀“ns”和命名空间urn:currentTime到WSDL服务和SOAP/XML信息。gSOAP工具使用特殊转化方式获得标识符名字:命名空间前缀后跟两个下划线。之因此如此处理命名空间,是为了不命名冲突。命名空间前缀“ns”经过“//gsoap”指令绑定到
urn:currentTime命名空间。
//gsoap指令用来设置服务属性,在本例中有
name、
namespace和
location。
CGI的服务实现须要在soap上下文上调用soap_serve,soap环境经过soap_new建立。服务的具体实现就像一个函数,该函数由RPC调度器使用soap_servey调用:
// File: currentTime.cpp
#include "soapH.h" // include the generated declarations
#include "currentTime.nsmap" // include the XML namespace mappings
int main()
{
// create soap context and serve one CGI-based request:
return soap_serve(soap_new());
}
int ns__currentTime(struct soap *soap, time_t& response)
{
response = time(0);
return SOAP_OK;
}
注意,咱们传递带有soap上下文信息的soap结构给服务例程。这很是方便于肯定链接的性能,还可使用soap_malloc(soap, num_bytes)动态申请空间,以及在服务结束时动态删除他们。
咱们运行soapcpp2编译器,生成服务端代码:
soapcpp2 -S currentTime.h
接着编译获得CGI二进制程序:
c++ -o currentTime.cgi currentTime.cpp soapC.cpp soapServer.cpp stdsoap2.cpp
stdsoap2.cpp能够在gsoap目录下找到。或者,若是你安装了gsoap,你能够选择连接libgsoap++库,就不用使用
stdsoap2.cpp源码了,像这样:
c++ -o currentTime.cgi currentTime.cpp soapC.cpp soapServer.cpp -lgsoap++
为了激活这个服务,将生成的
currentTime.cgi二进制程序拷贝到bin-cgi目录下,并赋以恰当的权限。
soapcpp2工具生成WSDL描述文件currentTime.wsdl。你可使用这个WSDL发布你的服务。你不须要使用这个WSDL去开发客户端。由于你已经有了
currentTime.h,使用soapcpp2的-C选项能够生成客户端代码。(注:参考1.2节)
CGI能够方便的经过标准I/O交换信息。所以,咱们使用自动生成的请求样例代码来测试:
./currentTime.cgi < currentTime.currentTime.req.xml
这样,获得的返回也是SOAP XML。
上面的过程一样适用于纯C语言。只须要在soapcpp2的-S选项后添加-c选项就能够生成ANSI C代码。固然,在C语言中咱们使用指针而不是引用,同时
currentTime.h文件也必须只能使用C类型。
另外还有一个更优雅的C++服务端实现:使用soapcpp2的-i(或-j)选项生成C++的客户端和服务端的服务类,使用这个类同时能够构建客户端也能够构建服务端。使用这个选项就不须要
soapClient.cpp和
soapServer.cpp了,由于咱们有了客户端和服务端的类实现:
soapcpp2 -i -S currentTime.h
这样就会生成
soapcurrentTimeService.h和
soapcurrentTimeService.cpp文件,以及辅助文件
soapStub.h和
currentTime.nsmap。
使用
currentTimeService对象,咱们重写CGI服务:
// File: currentTime.cpp
#include "soapcurrentTimeService.h" // include the proxy declarations
#include "currentTime.nsmap" // include the XML namespace mappings
int main()
{
// create server and serve one CGI-based request:
currentTimeService server;
return server.serve();
}
int currentTimeService::currentTime(time_t& response)
{
response = time(0);
return SOAP_OK;
}
编译:
c++ -o currentTime.cgi currentTime.cpp soapC.cpp soapcurrentTimeService.cpp -lgsoap++
接着安装CGI二进制文件。安装方法请查阅Web服务文档。
若是想在8080端口上以迭代方式运行服务,可使用:
return currentTimeService.run(8080);
想实现线程服务,请查看7.2.4节。该节讲述了经过多个线程来处理多个SO来请求。线程池也可使用。
7.2.7节有更多的服务端类的描述。7.1.4节有更多的客户端代理类的描述。
1.4 快速开始: XML数据绑定(待续)
1.5 特点概述(待续)
2 符号转换约定(待续)
3 版本2.4(包括以前的版本)与版本2.5的区别(待续)
4 版本2.1(包括以前的版本)与版本2.2的区别(待续)
5 gSOAP版本1.X和版本2.X之间的区别(待续)
6 互操做性(待续)
7 快速用户指南
这个用户指南提供快速的方式来使用gSOAP。理解本节须要对SOAP协议有一个基本的理解,还须要熟悉C/C++。若是你对SOAP协议没有深刻的了解,你也可使用gSOAP开发 C/C++的基于SOAP的C/S程序,不过,前提是客户端和服务端一致而且只在小组内通讯(即,你不须要担忧其余SOAP实现的互操做性)。本节开始说明gSOAP Web服务端和客户端的实现,进而说明与其余SOAP实现的互操做性,好比Apache Axis、SOAP::Lite和.NET。这须要了解SOAP和WSDL协议细节。
7.1 如何构建SOAP/XML 客户端
通常状况下,SOAP客户端程序的实现须要一个存根(也称作服务代理),该存根提供客户端调用服务的操做。存根的主要职责是处理参数,经过网络向指定的服务端发送请求,并等待应答,应答到来后再将参数解析出来。客户端只须要调用存根提供的例程,就像调用本地的函数同样。手工编写存根例程是很是麻烦的,特别是当输入输入参数涉及到复杂数据结构,如对象、结构体、容器、数组及指针指向的图形结构。幸运的是,gSOAP wsdl2h WSDL解析工具和soapcpp2存根生成器和序列化代码生成器可自动开发Web Service客户端和服务端。
soapcpp2生成必要的胶水代码(也称做存根或框架)来构建客户端和服务端。soapcpp2输入一个注解服务的C/C++头文件。该头文件能够经过wsdl2h解析工具生成,该工具须要一个WSDL文档。
考虑下面的命令:
wsdl2h -o calc.h http://www.genivia.com/calc.wsdl
这将生成一个C++头文件,该文件描述了服务的定义。