gSOAP 入门
1 简介
1.1 准备工作
使用gSOAP工具构建Web services应用程序或实现自动化XML数据绑定,你需要具备如下条件:
- 从http://www.genivia.com/Products/downloads.html下载gSOAP软件包。(选择标准版)
- C或C++编译器
- 如想支持SSL(HTTPS)和压缩,你还需要安装OpenSSL、Zlib库.这些库适用于大多数平台,同时通常也是已经安装好的。
- wsdl2h :WSDL/模式导入和数据映射绑定工具。(注:该工具将wsdl转换为开发用的.h文件)
- soapcpp2 :存根/框架编译器和代码生成器。(注:该工具依据.h文件自动生成部分C/CPP语言代码)
尽管gSOAP为不同平台准备了二进制格式的工具,但他们生成的代码是等价的。这意味着生成的源代码可以移植到其他平台并进行本地化编译。
gSOAP引擎可以被构建成libgsoap.a和libgsoap++.a库,后者支持SSL。参照README.txt的指示可以看到如何通过gSOAP包里的autoconf和automake构建与平台无关的库。或者,你将引擎的源代码stdsoap2.c(或stdsoap2.cpp)直接编译并链接进你们工程里。(注:说明gSOAP提供两种使用方式 ,一种编译成动态链接库,或者直接将源代码编译进工程)
1.2 快速开始:开发一个Web Service客户端应用程序
wsdl2h -o calc.h http://www.genivia.com/calc.wsdl
使用wsdl2h生成的服务定义头文件同样包含如何调用服务的信息。
在这个例子中,我们开发一个基于C++的计算器服务。默认情况下,gSOAP假定我们使用C++的STL。如不想使用STL,使用选项-s:
wsdl2h -s -o calc.h http://www.genivia.com/calc.wsdl
到现在为止,我们还没有生成C/C++的存根。为了生成它,我们使用soapcpp2编译器:
soapcpp2 -i -C -Iimport calc.h
选项-i指示我们希望得到C++代理和包含客户端(服务端)代码的对象。-C指示只生成客户端对象(默认情况下,gsoapcpp2同时生成客户端和服务端对象)。选项-I指示需要从import目录引入stl vector.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++的客户端)
1.3 快速开始:开发Web 服务
// 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);
// 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; }
soapcpp2 -S currentTime.h
接着编译得到CGI二进制程序:
c++ -o currentTime.cgi currentTime.cpp soapC.cpp soapServer.cpp stdsoap2.cpp
CGI可以方便的通过标准I/O交换信息。因此,我们使用自动生成的请求样例代码来测试:
./currentTime.cgi < currentTime.currentTime.req.xml
这样,得到的返回也是SOAP XML。
另外还有一个更优雅的C++服务端实现:使用soapcpp2的-i(或-j)选项生成C++的客户端和服务端的服务类,使用这个类同时可以构建客户端也可以构建服务端。使用这个选项就不需要 soapClient.cpp和 soapServer.cpp了,因为我们有了客户端和服务端的类实现:
soapcpp2 -i -S currentTime.h
// 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);