【翻译】gSOAP 2.8.5 用户手册(待续)

爷,独闯天下 提交于 2020-04-23 14:49:15

                        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指令用来设置服务属性,在本例中有 namenamespacelocation

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.cppsoapServer.cpp了,因为我们有了客户端和服务端的类实现:
soapcpp2 -i -S currentTime.h

这样就会生成 soapcurrentTimeService.hsoapcurrentTimeService.cpp文件,以及辅助文件 soapStub.hcurrentTime.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++头文件,该文件描述了服务的定义。



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!