gsoap使用总结

来源:互联网 发布:js 判断是否隐藏 编辑:程序博客网 时间:2024/05/22 15:50

gsoap使用总结

gSOAP简介

gSOAP是一个开发SOAP和XML应用(它们组成了webservice)的工具,在英文中叫toolkit。它是跨平台的,webservice的客户端和服务器端,都可以用它来辅助开发。它主要的功能(特征)如下:

  • C/C++数据绑定工具,支持XML-RPCfrom/to JSON from/to C/C++ serialization
  • 支持WSDL 1.1,2.0, SOAP 1.1, 1.2
  • 支持REST HTTP(S) 1.0/1.1 operations (GET,PUT,POST etc) for XML, JSON,etc
  • 支持MIME and MTOM 附件
  • 支持IPv4,IPv6, TCP 和UDP
  • 支持CGI,FastCGI
  • 支持嵌入到Apache,IIS中发布
  • 自带了一个Web server (multithreaded, SSL, compression)用于发布
  • 可适用于WinCE, Palm, Symbian, VxWorks, Andriod, iPhone等小设备

相关链接:

SOAP扫盲:  http://www.runoob.com/soap/soap-tutorial.html

gSOAP 2.8.34 User Guide:http://www.cs.fsu.edu/~engelen/soapdoc2.html

gsoap主页:http://www.cs.fsu.edu/~engelen/soap.html


GSOAP工具使用:

1.   wsdl2h的用法

该工具是可以根据输入的wsdlXSDURL,产生相应的C/C++形式的.h头文件,供soapcpp2使用。也就是从网络(本地)获取.wsdl文件生成头文件,soapcpp2根据生成的头文件生成代码框架。

参数:

选项

描述

-a

对匿名类型,产生基于顺序号的结构体名称

-c

生成C代码

-f

schema扩展,产生flat C++

-g

产生全局的元素声明

-h

显示帮助信息

-I path

包含文件时指明路径,相当于#import

-j

不产生 SOAP_ENV__Header SOAP_ENV__Detail 定义

-k

不产生 SOAP_ENV__Header mustUnderstand qualifiers

-l

在输出中包含license信息

-m

 xsd.h 模块来引入类型信息

-N name

name 来指定服务命名空间的前缀。

-n name

name 作为命名空间的前缀,取代缺省的ns

-o file

输出文件名

-q name

所有的声明采用 name 作命名空间

-s

不产生 STL代码 (即不用 std::stringstd::vector)

-t file

使用自己指定的type map file而不是缺省的typemap.dat

-u

不生成 unions

-v

产生详细的输出信息

-w

always wrap response parameters in a response struct

-y

structsenums产生 typedef定义

-_

不产生 _USCORE (UNICODE _x005f代替)

-?

显示帮助信息

 

2 soapcpp2的用法

根据头文件生成特定的代码框架。

参数:

选项

描述

-1

Soap1.1绑定

-2

SOAP1.2绑定

-C

只生成客户端代码

-S

只生成服务器端代码

-T

生成自动测试代码

-L

不生成 soapClientLib/soapServerLib

-a

 SOAPAction WS-Addressing调用服务器端方法

-A

 SOAPAction 调用服务器端方法

-b

采用char[N]这样的方式来表示string

-c

生成的是C代码,不是C++代码

-d < path >

将代码生成在 < path >

-e

生成 SOAP RPC 样式的绑定

-f N

File split of N XML serializer implementations per file

-h

显示一个简要的用法信息

-i

生成的服务代理类和对象从struct soap继承而来

-j

生成的服务代理类和对象包含struct soap而来(C代码的唯一选择)

-I < path >

包含其他文件时使用,指明 < path > (多个的话,用`:'分割),相当于#import ,该路径一般是gSOAP目录下的import目录,该目录下有一堆文件供soapcpp2生成代码时使用。

-n

用于生成支持多个客户端和服务器端(具体内容参考gSOAP文档)

-p < name >

生成的文件前缀采用< name > ,而不是缺省的 "soap"

-q < name >

C++代码中,所有声明的命名空间

-s

生成的代码在反序列化时,严格检查XML的有效性

-t

生成的代码在发送消息时,采用xsi:type方式

-u

 WSDL/schema 输出文件中不产生XML注释

-v

显示版本信息

-w

不生成 WSDL  schema 文件

-x

不生成 XML 形式的传输消息文件

-y

XML 形式的传输消息文件中,包含 C/C++类型信息

 

3 生成文件结构

文件

描述

soapStub.h

根据输入的.h文件生成的数据定义文件,一般我们不直接引用它。

soapH.h

soapC.cpp

客户端和服务器端应包含该头文件,它包含了soapStub.h。针对soapStub.h中的数据类型,cpp文件实现了序列化、反序列化方法。

soapXYZProxy.h

soapXYZProxy.cpp

这两个文件用于客户端,是客户端调用webservice的框架文件,我们的代码主要在此实现或从它继承。

soapXYZService.h

soapXYZService.cpp

这两个文件用于服务器端,是服务器端实现webservice的框架文件,我们的代码主要在此实现或从它继承。

.xsd

传输消息的schema,,我们可以看看是否满足我们的协议格式(如果有此要求)

.wsdl

这个就不用说了。

.xml

满足webservice定义的例子message,即实际的传输消息,我们可以看看是否满足我们的协议格式(如果有此要求)。

.nsmap

命名空间的定义,对命名空间不敏感的,不用关注。

soapClient.cpp

客户端代码框架

soapClientLib.cpp

客户端代码框架(一般不使用)

 

Eg:在dos界面下键入:

D:\setup\gsoap-2.8\gsoap\bin\win32\wsdl2h-s -o  onvif.h -t  D:\setup\gsoap-2.8\gsoap\bin\win32\typemap.dat

http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl  

http://www.onvif.org/onvif/ver20/analytics/wsdl/analytics.wsdl  

http://www.onvif.org/onvif/ver10/analyticsdevice.wsdl  

http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl  

http://www.onvif.org/onvif/ver10/deviceio.wsdl  

http://www.onvif.org/onvif/ver10/display.wsdl  

http://www.onvif.org/onvif/ver10/event/wsdl/event.wsdl  

http://www.onvif.org/onvif/ver20/imaging/wsdl/imaging.wsdl  

http://www.onvif.org/onvif/ver10/recording.wsdl  

http://www.onvif.org/onvif/ver10/replay.wsdl  

http://www.onvif.org/onvif/ver10/search.wsdl  

http://www.onvif.org/onvif/ver10/receiver.wsdl  

http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl

执行完成会生成:onvif.h文件

 

键入:

D:\setup\gsoap-2.8\gsoap\bin\win32\soapcpp2 -c -x  D:\setup\gsoap-2.8\gsoap\bin\win32\onvif.h -I D:\setup\gsoap-2.8\gsoap\import –I D:\setup\gsoap-2.8\gsoap

就会生成我们需要的代码框架。


Webserver开发

开发两种方式

API接口固定,不关心底层的通讯,将SOAP作为应用层协议。

当我们拥有头文件(或者自己编写头文件时候,常见用于服务端)

通讯协议固定(当然需要基于XML的)或只有wsdl,将SOAP作为传输层协议

我们能够获取到wsdl文件时候(常见用于客户端)

接口定义

前缀:必须以ns加两个下划线开始。返回值必须是int
int ns__add( int a, int b, int *c );

多个参数传出(传回),在接口中必须使用结构体
typedef char * xsd__string;

typedef long xsd__int;

struct ns__personResponse
{

xsd__int age;
xsd__string name;

xsd__string address;

};
int ns__person( xsd__string buf_in, structns__personResponse * buf_out );

接口中的下划线,如果接口中的交易名有下划线,必须这么声明:
int ns__echo_USCOREreverse( char * buf_in, char ** buf_out );

 

注意事项:

嵌套结构体写法:父级结构体无需使用ns__返回的目标结构成员的名字必须是__ptr,大小的名字必须是__size

1.  struct ArrayOfEmp  //此处不要 ns__ ArrayOfEmp 

2. {struct ns__EmployeeInfo **__ptr;int __size;}; 

中文支持

1. 设置gsoap为utf-8传输数据
soap_set_mode( &SmsWBS_soap, SOAP_C_UTFSTRING ); //设置编码SmsWBS_soap.mode|=SOAP_C_UTFSTRING;
<pre name="code" class="html" style="color: rgb(17, 17, 17); font-size: 14px; font-weight: bold;">2. 使用下面得函数转换我们的传输内容,即将我们的数据转成UTF-8编码:

int conv_charset( const char *dest, const char *src, char *input, size_t ilen,char *output, size_t olen ){int convlen = olen;iconv_t conv = iconv_open( dest, src );if( conv == (iconv_t) -1 )return -1;memset( output, 0, olen );if( iconv( conv, &input, &ilen, &output, &olen ) ){iconv_close(conv);return -1;}iconv_close(conv);return convlen-olen;}
例子: conv_charset( "UTF-8", "GBK", "微软.linxr", strlen("微软.linxr"), buf_out->name,100 );

初始化:

Function

Description

soap_init(struct soap *soap)

初始化运行的环境

soap_init1(struct soap *soap, soap_mode iomode)

初始化运行的环境并设置模式

soap_init2(struct soap *soap, soap_mode imode, soap_mode omode)

初始化运行的环境并设置模式

struct soap *soap_new()

返回一个初始化过的soap指针

struct soap *soap_new1(soap_mode iomode)

返回一个初始化并设置模式后的soap指针

struct soap *soap_new2(soap_mode imode, soap_mode omode)

返回一个初始化并设置模式后的soap指针

struct soap *soap_copy(struct soap *soap)

拷贝一个soap


Function Call

Description

soap_destroy(struct soap *soap)

释放所有动态分配的C++类,必须在soap_end()之前调用。

soap_end(struct soap *soap)

释放所有存储临时数据和反序列化数据中除类之外的空间(soap_malloc的数据也属于反序列化数据)。

soap_done(struct soap *soap)

Detach soap结构(即初始化化soap结构)

soap_free(struct soap *soap)

Detach 且释放soap结构


例如:
#include "soapH.h" // include all interfaces (library and generated) #include "calc.nsmap" // import the generated namespace mapping table int main() {    double sum; //初始化   struct soap soap; // the gSOAP runtime context    soap_init(&soap); // initialize the context (only once!) //方法调用   if (soap_call_c__add(&soap, NULL, NULL, 1.0, 2.0, &sum) == SOAP_OK)       std::cout << "Sum = " << sum << std::endl;    else // an error occurred       soap_print_fault(&soap, stderr); // display the SOAP fault message on the stderr stream //释放资源   soap_destroy(&soap); // delete deserialized class instances (for C++)    soap_end(&soap); // remove deserialized data and clean up    soap_done(&soap); // detach the gSOAP context    return 0; }


webServer发布

要能被其他人引用,别人需要获得我们的wsdl文件,获取到webServer后就会获取到我们的webServer方法。

 

假定我们定义:struct soap Server;

其实就是实现: Server.fget 的函数指针


int   http_get(struct   soap   *soap) { FILE*fd = NULL;char *s = strchr( soap->path, '?' );if( !s || strcmp( s, "?wsdl" ) ){return SOAP_GET_METHOD;}fd = fopen(".\\Server.wsdl", "rb"); //open WSDL file to copyif (!fd){return 404; //return HTTP not found error}soap->http_content = "text/xml";  //HTTP header with text /xml contentsoap_response(soap,SOAP_FILE);for(;;){size_t r = fread(soap->tmpbuf,1, sizeof(soap->tmpbuf), fd);if (!r){break;}if (soap_send_raw(soap, soap->tmpbuf, r)){break; //cannot send, but little we can do about that}}fclose(fd);soap_end_send(soap);return SOAP_OK; }

实例

1 通过获取wsdl生成头文件

在dos界面下键入:

wsdl2h -c -s -oF:\学习资料\gsoap\demo\general\calc.h http://www.genivia.com/calc.wsdl

说明:

wsdl2h可以加上完整路径,本机由于加入到了环境变量,所以无需绝对路径。

在F:\学习资料\gsoap\demo\general\路径下将会生成calc.h头文件。

 

头文件里面包含信息:

//gsoap ns2 service name:   calc

//gsoap ns2 service type:     calcPortType

//gsoap ns2 service port:     http://websrv.cs.fsu.edu/~engelen/calcserver.cgi

//gsoap ns2 service namespace: urn:calc

//gsoap ns2 service transport:     http://schemas.xmlsoap.org/soap/http

//gsoap ns2   schema namespace:       urn:calc

//gsoap ns2   schema form: unqualified

 

//gsoap ns2 service method-protocol: add SOAP

//gsoap ns2 service method-style:       add rpc

//gsoap ns2 service method-encoding:        addhttp://schemas.xmlsoap.org/soap/encoding/

//gsoap ns2 service method-action:    add""

//gsoap ns2 service method-output-action:         addResponse

 ......

假定我们自定义头文件:

//gsoap ns service name: Test 

//gsoap ns service namespace:http://202.115.52.165:4567/Test.wsdl 

//gsoap ns service location:http://202.115.52.165:4567

//gsoap ns service executable:Test.cgi 

//gsoap ns service encoding:encoded 

//gsoap ns schema namespace: urn:Test

int ns2__add(

    double                              a,  ///< Input parameter, : unqualified name asper RPC encoding

    double                              b,  ///< Input parameter, : unqualified name asper RPC encoding

    double                             *result  ///< Output parameter, : unqualified nameas per RPC encoding

);

int ns2__sub(

    double                              a,  ///< Input parameter, : unqualified name asper RPC encoding

    double                              b,  ///< Input parameter, : unqualified name asper RPC encoding

    double                             *result  ///<Output parameter, : unqualified name as per RPC encoding

);

int ns2__mul(

    double                              a,  ///< Input parameter, : unqualified name asper RPC encoding

    double                              b,  ///< Input parameter, : unqualified name asper RPC encoding

    double                             *result  ///< Output parameter, : unqualified nameas per RPC encoding

);

int ns2__div(

    double                              a,  ///< Input parameter, : unqualified name asper RPC encoding

    double                              b,  ///< Input parameter, : unqualified name asper RPC encoding

    double                             *result  ///< Output parameter, : unqualified nameas per RPC encoding

);

int ns2__pow(

    double                              a,  ///< Input parameter, : unqualified name asper RPC encoding

    double                              b,  ///< Input parameter, : unqualified name asper RPC encoding

    double                             *result  ///< Output parameter, : unqualified nameas per RPC encoding

);

2   生成服务端和客户端框架代码

在dos界面键入:

         soapcpp2 -2 -l -d F:\学习资料\gsoap\demo\general\F:\学习资料\gsoap\demo\general\calc.h

说明:

-2 用soap2绑定 –l 不生成lib文件 –d 输出路径  最后是你的头文件路径


3   创建服务端工程

步骤:

初始化soap

绑定IP和端口

等待连接

处理请求   

释放资源

另外:还需要实现自己发布方法的逻辑,在soapStub.h文件里面有包含了方法名。一般由:SOAP_FMAC5 intSOAP_FMAC6打头。也就是自定义头文件的函数。

假定你实现了gsoap.fget函数指针,就可以在浏览器获取到你的wsdl文件了(详细见工程链接:文档底部),浏览器获取一此会调用http_get两次。

#include <iostream>#include "stdsoap2.h"#include "soapH.h"#include "ns2.nsmap"struct soap g_Server;//定义服务端的soapint   http_get(struct   soap   *soap);int main(){//初始化soapsoap_init(&g_Server);//发布webserver需要实现g_Server.fget = http_get;//绑定IP和端口int ret = soap_bind(&g_Server, "202.115.52.176", 4567, 100);if (ret < 0){soap_print_fault(&g_Server, stderr);exit(-1);}std::cout << "webServer运行!" << std::endl;while (true){//等待连接int s = soap_accept(&g_Server);if (s < 0){//连接失败break;}soap_serve(&g_Server);//资源释放soap_destroy(&g_Server);soap_end(&g_Server);}soap_done(&g_Server);return 0;}int   http_get(struct   soap   *soap){std::cout << "调用WSDL!" << std::endl;FILE*fd = NULL;char *s = strchr(soap->path, '?');if (!s || strcmp(s, "?wsdl")){return SOAP_GET_METHOD;}fd = fopen(".\\ns2.wsdl", "rb"); //open WSDL file to copyif (!fd){return 404; //return HTTP not found error}soap->http_content = "text/xml";  //HTTP header with text /xml contentsoap_response(soap, SOAP_FILE);for (;;){size_t r = fread(soap->tmpbuf, 1, sizeof(soap->tmpbuf), fd);if (!r){break;}if (soap_send_raw(soap, soap->tmpbuf, r)){break; //cannot send, but little we can do about that}}fclose(fd);soap_end_send(soap);return SOAP_OK;}//加法实现int ns2__add(struct soap*g_Server, double a, double b, double *result){*result = a + b;std::cout << a << "+" << b << "=" << *result << std::endl;soap_end_send(g_Server);return SOAP_OK;}//加法实现int ns2__sub(struct soap *g_Server, double a, double b, double*res){*res = a - b;std::cout << a << "-" << b << "=" << res << std::endl;soap_end_send(g_Server);return SOAP_OK;}//乘法实现int ns2__mul(struct soap *g_Server, double a, double b, double*res){*res = a * b;std::cout << a << "*" << b << "=" << res << std::endl;soap_end_send(g_Server);return SOAP_OK;}//除法实现int ns2__div(struct soap *g_Server, double a, double b, double*res){if (b==0){std::cout << "除数不能为空!" << std::endl;return SOAP_FATAL_ERROR;}*res = a /b;std::cout << a << "/" << b << "=" << res<<std::endl;soap_end_send(g_Server);return SOAP_OK;}//除法实现int ns2__pow(struct soap *g_Server, double a, double b, double*res){*res = pow( a,b);std::cout <<"pow(" <<a << "," << b << ") "<<"=" << res << std::endl;soap_end_send(g_Server);return SOAP_OK;}


4   创建客户端工程

创建soap,并初始化。

调用webserver方法

最后释放资源

<span style="white-space:pre"></span>struct soap add_soap;soap_init(&add_soap);int result = -1;char* server = "http://202.115.52.176:4567";double a = 1.2;double b = 1.3;double res=0;soap_call_ns2__add(&add_soap, server, "", a, b, &res);if (add_soap.error){std::cout << "soap error:" << add_soap.error << "," << *soap_faultcode(&add_soap) << "," << *soap_faultstring(&add_soap) << std::endl;res = add_soap.error;return 0;}std::cout << a << "+" << b << "=" <<res<< std::endl;soap_end(&add_soap);


代码工程链接:http://download.csdn.net/detail/hl2015222050145/9622515



0 0
原创粉丝点击