C++中如何使用gsoap开发WebService

Posted on 2011-03-12 15:37  Jophoenix  阅读(4542)  评论(0编辑  收藏  举报

1. 什么是gSOAP
gSOAP是一个夸平台的,用于开发Web Service服务端和客户端的工具,在Windows、Linux、MAC OS和UNIX下使用C和C++语言编码,集合了SSL功能。gSOAP是一个开源的项目,用它可以方便的使用c/c++地进行SOAP客户端和服务器端编程,而不必了解xml和SOAP协议的细节。

2. 如何获取gSOAP
官网地址:
http://genivia.com/Products/gsoap/index.html
开源主页地址:
http://gsoap2.sourceforge.net/
目前版本为2.8.0
http://sourceforge.net/projects/gsoap2/files/gSOAP/gsoap_2.8.0.zip/download

3.生成WSDL
访问http://localhost/HelloWorld.asmx,在该页面中点击【服务说明】,即生成了http://localhost/HelloWorld.asmx?WSDL

4.根据WSDL文件,生成函数描述
在gSOAP中,提供了两个工具,wsdl2h和soapcpp2,用这两个工具来帮我们生成代理函数。

在cmd下运行这两个工具:

// 查看帮助
wsdl2h -h

Usage: wsdl2h [-a] [-c] [-d] [-e] [-f] [-g] [-h] [-I path] [-i] [-j] [-k] [-l] [
-m] [-n name] [-N name] [-p|-P] [-q name] [-r proxyhost[:port[:uid:pwd]]] [-s] [
-t typemapfile] [-u] [-v] [-w] [-W] [-x] [-y] [-z#] [-_] [-o outfile.h] infile.w
sdl infile.xsd http://www/... ...

-a      generate indexed struct names for local elements with anonymous types
-c      generate C source code
-d      use DOM to populate xs:any, xs:anyType, and xs:anyAttribute
-e      don't qualify enum names
-f      generate flat C++ class hierarchy
-g      generate global top-level element declarations
-h      display help info
-i      don't import (advanced option)
-Ipath  use path to find files
-j      don't generate SOAP_ENV__Header and SOAP_ENV__Detail definitions
-k      don't generate SOAP_ENV__Header mustUnderstand qualifiers
-l      display license information
-m      use xsd.h module to import primitive types
-nname  use name as the base namespace prefix instead of 'ns'
-Nname  use name as the base namespace prefix for service namespaces
-ofile  output to file
-p      create polymorphic types with C++ inheritance from base xsd__anyType
-P      don't create polymorphic types with C++ inheritance from xsd__anyType
-qname  use name for the C++ namespace of all declarations
-rhost[:port[:uid:pwd]]
        connect via proxy host, port, and proxy credentials
-s      don't generate STL code (no std::string and no std::vector)
-tfile  use type map file instead of the default file typemap.dat
-u      don't generate unions
-v      verbose output
-w      always wrap response parameters in a response struct (<=1.1.4 behavior)
-W      suppress warnings
-x      don't generate _XML any/anyAttribute extensibility elements
-y      generate typedef synonyms for structs and enums
-z1     compatibility with 2.7.6e: generate pointer-based arrays
-z2     compatibility with 2.7.15: qualify element/attribute referenced members
-_      don't generate _USCORE (replace with UNICODE _x005f)
infile.wsdl infile.xsd http://www/... list of input sources (if none: use stdin)

soapcpp2 -h

Usage: soapcpp2 [-1|-2] [-C|-S] [-T] [-L] [-a] [-b] [-c] [-d path] [-e] [-h] [-i
] [-I path;path;...] [-l] [-m] [-n] [-p name] [-s] [-t] [-v] [-w] [-x] [infile]

-1      generate SOAP 1.1 bindings
-2      generate SOAP 1.2 bindings
-C      generate client-side code only
-S      generate server-side code only
-T      generate server auto-test code
-L      don't generate soapClientLib/soapServerLib
-a      use SOAPAction HTTP/WSA header to invoke server-side operations
-b      serialize byte arrays char[N] as string
-c      generate C source code
-dpath  use path to save files
-e      generate SOAP RPC encoding style bindings
-h      display help info
-i      generate service proxies and objects inherited from soap struct
-Ipath  use path(s) for #import
-l      generate linkable modules (experimental)
-m      generate Matlab(tm) code for MEX compiler
-n      use service name to rename service functions and namespace table
-pname  save files with new prefix name instead of 'soap'
-qname  use name as the C++ namespace of all declarations
-s      generate deserialization code with strict XML validation checks
-t      generate code for fully xsi:type typed SOAP/XML messaging
-v      display version info
-w      don't generate WSDL and schema files
-x      don't generate sample XML message files
infile  header file to parse (or stdin)

使用wsdl2h生成头文件

wsdl2h -c -o TestWebservice.h http://localhost/HelloWorld.asmx?WSDL

-c 表示用纯c语言来实现,如果不加-c,则用c++语言来实现
-o 表示指定输出文件名称

使用soapcpp2来生成代理函数

soapcpp2 -c TestWebservice.h

执行后,会产生若干个h文件和c文件,里面包含了对远程函数的封装。

本例中生成了以下文件:
soapH.h soapServer.c soapServerLib.c soapClient.c soapClientLib.c soapStub.h soapC.c HelloWorldSoap.nsmap

5. 建立一个控制台程序,将soapH.h soapClient.c soapClientLib.c soapStub.h soapC.c HelloWorldSoap.nsmap添加到工程中

主程序代码如下:

 

 1 #include "stdio.h"
 2 #include "soapH.h" // or whatever it is called, you must already have it
 3 #include "HelloWorld.nsmap" // this is what you have to add to fix the problem
 4 
 5 void main()
 6 {
 7  struct soap stSoap;
 8  struct _ns1__HelloWorld stHelloWorld;
 9  struct _ns1__HelloWorldResponse stHelloWorldRes;
10 
11  soap_init(&stSoap);
12  
13  if(soap_call___ns2__HelloWorld(&stSoap,NULL,NULL,&stHelloWorld,&stHelloWorldRes)==SOAP_OK)
14  {
15   printf("%s!\n",stHelloWorldRes.HelloWorldResult);
16  }
17  else
18  {
19   printf("Call Failed!\n");
20  }
21 
22  system("pause");
23 
24  soap_destroy(&stSoap); 
25  soap_end(&stSoap); 
26  soap_done(&stSoap);
27 }

 

编译...
>fatal error C1083: Cannot open include file: 'stdsoap2.h': No such file or directory

缺少头文件,OK,需要将stdsoap2.h/stdsoap2.c 拷到工程目录下,并添加到工程中。

再编译...
>soapClientLib.obj : error LNK2005: _soap_call___ns2__HelloWorld already defined in soapClient.obj

查看生成的soapClientLib.c文件,发现如下代码:

#ifndef WITH_NOGLOBAL
#define WITH_NOGLOBAL
#endif
#define SOAP_FMAC3 static
#include "soapC.c"
#include "soapClient.c"

/* End of soapClientLib.c */

之前已经添加soapC.c,soapClient.c,可以去掉soapClientLib.c了。

再编译...
Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped

6. 运行
又看到了我们熟悉的窗口:HelloWorld!

17加油!