[1].gSOAP简介

 

 

gSOAP 简介

      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工具支持传统的C/C++代码(以及留有C接口的其他编程语言)、嵌入式系统、那些和其他SOAP程序共享计算资源和信息的实时SOAP/XML应用程序之间的集成,可以跨平台,适用不同的语言环境和穿透防火墙。  gSOAP工具常常使用C/C++实现XML数据绑定。这意味着程序本地数据结构可被自动地用XML编码,而不需要额外去编写转换代码。该工具还为了XML数据绑定生成XML模式,所以外部程序可以基于该模式使用XML数据。

1.1  快速入门

使用gSOAP工具构建Web services应用程序或实现自动化XML数据绑定,你需要具备如下条件:

  • http://www.genivia.com/Products/downloads.html下载gSOAP软件包。(选择标准版)
  • 一个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基于相同的开源标准发布的。

    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


     这样就生成了描述服务操作定义及数据类型定义的头文件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++计算器客户端,我们使用生成的soapcalcProxy类和XML命名空间映射表calc.nsmap来访问Web服务。该soapcalcProxy类是调用服务的一个代理。:

#include "soapcalcProxy.h"
#include "calc.nsmap"
int 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);
   service.destroy(); // 删除数据释放内存
}


接下来我们编译并链接生成的soapC.cpp和soapcalcProxy.cpp,以及动态链接库-lgsoap++(如果你没有安装该库,可以将stdsoap2.cpp引入到你的代码)。(注:上面就构建完了基于C++的客户端).假定我们开发的是C语言客户端,那么我们可以这样: wsdl2h -c -o calc.h http://www.genivia.com/calc.wsdl and soapcpp2 -C calc.h。 这种情况下我们代码使用一个简单的C函数调用服务我们还需要显式使用soap_endsoap_free删除数据和上下文

#include "soapH.h"
#include "calc.nsmap"
int 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 Service

开发服务端程序也很简单。这里我们使用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;
   server.serve();
   server.destroy();
}
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端口上以迭代方式运行服务,可以使用:

while (server.run(8080) != SOAP_TCP_ERROR)
   server.soap_stream_fault(std::cerr);


想实现线程服务,请查看7.2.4节。该节讲述了通过多个线程来处理多个SO来请求。线程池也可以使用。7.2.7节有更多的服务端类的描述。7.1.4节有更多的客户端代理类的描述.

1.4  Q快速开始: XML 数据绑定

换句换说, C / C+自动读取和编写XML数据如何映射schemasXSD文件 gsoap 提供自动化的绑定机制可以将C/C++的数据绑定到XML里,任何C/C++的数据类型都可以. 一个XML模式XSD文件可转化为一组C或C ++的定义 ,比DOM或者SAX 解析方式更容易让你的程序使用. 从本质上来说, XML架构中的每个XML组件都对应着一个C / C++数据类型. 使用XSD来对class 进行映射优点显而易见:

XSD C++
<complexType name="Address"> class ns__Address
   <sequence> {
      <element name="name" type="string"/>    std::string name;
      <element name="home" type="tns:Location" minOccurs="0"/>    ns__Location *home;
      <element name="phone" type="unsignedLong"/>    ULONG64 phone;
      <element name="dob" type="dateTime"/>    time_t dob;
   </sequence>
   <attribute name="ID" type="int" use="required"/>    @int ID;
</complexType> }


通过这种方式, 不需要DOM遍历和SAX事件就能自动的在符合XML 架构的XML元素到类的成员的创建. 此外, C/C++ 数据绑定XML的操作是安全的.  类型安全就是是说 C/C++ 确保只有有效的XML文档可以解析和生成 wsdl2h工具自动执行WSDL和XML模型的映射到C/C++wsdl2h 输出 The output of wsdl2h is an annotated header file that includes comments and documentation on the use of the C/C++ declarations in a SOAP/XML client/server or in a generic application for reading and writing XML using the auto-generated serializers. We will illustrate this further with an example. Suppose we have an XML document with a book record:

<book isbn="1234567890">
   <title>Farewell John Doe</title>
   <publisher>ABC's is our Name</publisher>
</book>


可以用XML 来表示一个书本的元素和类型

<schema ...>
   <element name="book">
      <complexType>
         <sequence>
            <element name="title" type="string" minOccurs="1"/>
            <element name="publisher" type="string" minOccurs="1"/>
         </sequence>
         <attribute name="isbn" type="unsignedLong" use="required"/>
      </complexType>
   </element>
</schema>


  使用 wsdl2h 转换 XML schema 定义book 类型 到一个类,如下:

class book
{
   @ULONG64 isbn;
   std::string title;
   std::string publisher;
}


请注意上面的例子,是使用@来表示元素的属性的. 这些特殊的gSOAP注释是soapcpp2 工具生成的,用于对数据序列化读取和编写XML . soapcpp2  工具生成所有必要的代码来解析和生成XML对象. 验证如 minOccurs="1" 和 use="required"是否包含在生成的代码里. 用XML表示一本书, 我们首先创建一个SOAP(engine context ),并用它soap_write_booksoapcpp2生成的)使用标准输出XML中的对象:

soap *ctx = soap_new1(SOAP_XML_INDENT); // new context with option
book bk;
bk.isbn = 1234567890;
bk.title = "Farewell John Doe";
bk.publisher = "ABC's is our Name";
if (soap_write_book(ctx, &bk) != SOAP_OK)
   ... error ...
soap_destroy(ctx); // clean up allocated class instances
soap_end(ctx); // clean up allocated temporaries
soap_free(ctx); // delete context


 ctx gSOAP 上下文引擎 (soap 结构类型) 用于控制设置和状态保持的。 例如XML的格式化, (e.g. SOAP_XML_INDENT), 设置序列化选项, 获取当前状态,设置I/O. 只需要简单的设置输出流 (std::ostream) ctx->os 就能将上下文重定向到string 或文件里.此外,当序列化一个图表,在代码调用soap_put方法以确保输出符合对象图的SOAP编码(你也可以使用一个基于id-ref的编码)之前,先在对象或类型上调用串行器bk.soap_serializectx)。细节见7.5节,解析典型的xml成为一本书对象用:

soap *ctx = soap_new1(SOAP_XML_STRICT); // new context with option
book bk;
if (soap_read_book(ctx, &bk) != SOAP_OK)    ... error ...
else
   cout << bk.isbn << ", " << bk.title << ", " << bk.publisher << endl;
... further use of bk ...
soap_destroy(ctx); // delete deserialized objects
soap_end(ctx); // delete temporaries
soap_free(ctx); // delete context


Automatic built-in XML validation (enabled with SOAP_XML_STRICT) ensures that data members are present so we can safely print them in this example, thus ensuring consistency of data with the XML schema. Set the ctx->is input stream to read from a file/string stream instead of stdin. The soap_destroy and soap_end calls deallocate the deserialized content, so use with care. In general, memory management is automatic in gSOAP to avoid leaks. The above uses a very simple example schema. The gSOAP toolkit handles all XML schema constructs defined by the XML schema standard. The toolkit is also able to (de)serialize pointer-based C/C++ data structures (including cyclic graphs), structs/classes, unions, enums, STL containers, and even special data types such as struct tm. Therefore, the toolkit works in two directions: from WSDL/schema to C/C++ and from C/C++ to WSDL/schema. The gSOAP toolkit also handles multiple schemas defined in multiple namespaces. Normally the namespace prefixes of XML namespaces are added to the C/C++ type definitions to ensure type uniqueness. For example, if we would combine two schemas in the same application where both schemas define a book object, we need to resolve this conflict. In gSOAP this is done using namespace prefixes, rather than C++ namespaces (research has pointed out that XML namespaces are not equivalent to C++ namespaces). Thus, the book class might actually be bound to an XML namespace and the class would be named ns__book, where ns is bound to the corresponding namespace. The following options are available to control serialization:

soap->encodingStyle = NULL; // to remove SOAP 1.1/1.2 encodingStyle
soap_mode(soap, SOAP_XML_TREE); // XML without id-ref (no cycles!)
soap_mode(soap, SOAP_XML_GRAPH); // XML with id-ref (including cycles)
soap_set_namespaces(soap, struct Namespace *nsmap); //to set xmlns bindings


其他可用于XML 绑定的表示, 可以看 9.12 章节. 获得更多的XML绑定C/C++ 帮助,看 7.5章节.

1.5  功能概述

gSOAP的亮点:

  • 独特互操作性功能: 工具生成类型安全SOAP 编组程序(序列本地和用户定义的C和C+ +数据结构).
  • gSOAP支持WSDL 1.1, SOAP 1.1, SOAP 1.2, SOAP RPC 编码方式以及 literal/document 方式. gSOAP is one of the few SOAP toolkits that support the full range of SOAP 1.1 RPC encoding features including sparse multi-dimensional arrays and polymorphic types. For example, a service operation with a base class parameter may accept derived class instances from a client. Derived class instances keep their identity through dynamic binding. The toolkit also supports all XSD schema type constructs and has been tested against the W3C XML Schema Patterns for Databinding Interoperability working group and of gSOAP release 2.8.x passes all tests.
  • Supports WS-Security, WS-Addressing, WS-ReliableMessaging, C14N exclusive canonicalization. The protocols are implemented using code generation with wsdl2h and soapcpp2. The gSOAP tools can be used to generate messaging protocols for other WS-* protocols.
  • gSOAP supports XML-RPC and RSS protocols. Examples are provided.
  • JSON support is included in the XML-RPC library to switch between XML-RPC and JSON protocols. For more details, see the samples/xml-rpc-json folder in the package.
  • The wsdl2h tool supports WS-Policy. Policy assertions are included in the generated service description header file with recommendations and usage hints.
  • gSOAP supports MIME (SwA), DIME, and MTOM attachments and has streaming capabilities to direct the data stream to/from resources. gSOAP is the only toolkit that supports streaming MIME, DIME, and MTOM attachment transfers, which allows you to exchange binary data of practically unlimited size in the fastest possible way (streaming) while ensuring the usefulness of XML interoperability.
  • gSOAP 支持 SOAP-over-UDP
  • gSOAP 支持IPv4 and IPv6.
  • gSOAP 支持Zlib deflate and gzip compression (for HTTP, TCP/IP, and XML file storage).
  • gSOAP 支持 SSL (HTTPS) 使用 OpenSSL.
  • gSOAP 支持 HTTP/1.0, HTTP/1.1 keep-alive, chunking, basic authentication, and digest authentication using a plugin.
  • gSOAP 支持SOAP one-way messaging.
  • The schema-specific XML pull parser is fast and efficient and does not require intermediate data storage for demarshalling to save space and time.
  • The soapcpp2 compiler includes a WSDL and schema generator for convenient Web Service publishing.
  • The soapcpp2 compiler generates sample input and output messages for verification and testing (before writing any code). An option (-T) can be used to automatically implement echo message services for testing.
  • The WSDL importer wsld2h (converts to gSOAP header files) for automated client and server development.
  • Generates source code for stand-alone Web Services and client applications.
  • Ideal for small devices such as Palm OS, Symbian, Pocket PC, because the memory footprint is small.
  • Ideal for building web services that are compute-intensive and are therefore best written in C and C++.
  • Platform independent: Windows, Unix, Linux, Mac OS X, Pocket PC, Palm OS, Symbian, VXWorks, etc.
  • Supports serializing of application's native C and C++ data structures, which allows you to save and load XML serialized data structures to and from files.
  • Selective input and output buffering is used to increase efficiency, but full message buffering to determine HTTP message length is not used. Instead, a three-phase serialization method is used to determine message length. As a result, large data sets such as base64-encoded images can be transmitted with or without DIME attachments by small-memory devices such as PDAs.
  • Supports C++ single class inheritance, dynamic binding, overloading, arbitrary pointer structures such as lists, trees, graphs, cyclic graphs, fixed-size arrays, (multi-dimensional) dynamic arrays, enumerations, built-in XSD Schema types including base64Binary encoding, and hexBinary encoding.
  • No need to rewrite existing C/C++ applications for Web service deployment. However, parts of an application that use unions, pointers to sequences of elements in memory, and void* need to be modified, but only if the data structures that adopt them are required to be serialized or deserialized as part of a service operation invocation.
  • Three-phase marshalling: 1) analysis of pointers, single-reference, multi-reference, and cyclic data structures, 2) HTTP message-length determination, and 3) serialization as per SOAP 1.1 encoding style or user-defined encoding styles.
  • Two-phase demarshalling: 1) SOAP parsing and decoding, which involves the reconstruction of multi-reference and cyclic data structures from the payload, and 2) resolution of "forward" pointers (i.e. resolution of the forward href attributes in SOAP).
  • Full and customizable SOAP Fault processing (client receive and service send).
  • Customizable SOAP Header processing (send and receive), which for example enables easy transaction processing for the service to keep state information.

 

 

 

 

你可能感兴趣的:(SOAP)