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.htmlGSOAP工具使用:
1. wsdl2h的用法
该工具是可以根据输入的wsdl或XSD或URL,产生相应的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::string,std::vector)
-t file
使用自己指定的type map file而不是缺省的typemap.dat
-u
不生成 unions
-v
产生详细的输出信息
-w
always wrap response parameters in a response struct
-y
为structs,enums产生 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文件时候(常见用于客户端)
接口定义
n 前缀:必须以ns加两个下划线开始。返回值必须是int。
int ns__add( int a, int b, int *c );
n 多个参数传出(传回),在接口中必须使用结构体
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 );
n 接口中的下划线,如果接口中的交易名有下划线,必须这么声明:
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);
- gsoap使用总结
- gsoap使用总结
- gsoap使用总结
- gsoap使用总结
- gsoap使用总结
- gSoap使用总结
- gsoap使用总结
- gsoap使用总结
- gsoap使用总结
- gsoap使用总结
- gsoap使用总结
- gsoap使用总结
- gsoap使用总结
- webservice 前端gsoap 使用总结
- Unicode环境下使用Gsoap的总结
- gsoap使用总结 开发实例(windwos+VS2005)
- 使用gSOAP进行Webservice开发总结
- GSoap使用
- ECMAScript 6之变量的解构赋值
- PKI基础(一)
- Mybatis的查询操作之resultType和resultMap
- ifconfig 命令显示HCA卡IP地址的问题
- LightOJ1014 Ifter Party
- gsoap使用总结
- Nginx切割日志
- Oracle学习记录
- mysql一些简单操作
- 粒子群优化算法
- BiDi 算法详解及应用(一)
- MVC 下载文件
- 快速生成SpringBootDemo程序
- Python note