gsoap 在一个客户端中调用多个service的解决方案(本方案是在windows平台,mac平台一样)

<1>

刚开始开始接触soap协议之gsoap工具还很陌生,所以看网上教程怎么使用它。这篇我认为他讲的比较好:

1 基本流程

从Web服务提供者处获取Web Service的WSDL文件,通常是一个URL,

如:http://www.cs.fsu.edu/~engelen/calc.wsdl

当然也可以是一个WSDL形式的XML文件。

2 使用gSoap工具wsdl2h,根据WSDL生成一个C/C++语法结构的头文件。

如:wsdl2h -s -o calc.h http://www.cs.fsu.edu/~engelen/calc.wsdl

这一步将会得到一个头文件,如:calc.h

该步的目的:实现WSDL文件到.h文件的数据映射。

3. 使用gSoap的预编译器soapcpp2,根据上一步得到的头文件来生成存根文件(soapStub.h)和客户端代码框架。

如:soapcpp2 -i -x -C -L calc.h

这一步将会得到几个. nsmap、.h和.cpp文件,如:calc.nsmap、soapC.cpp、soapH.h、soapStub.h、soapcalcProxy.cpp、soapcalcProxy.h

该步的目的:生成相应的底层通信代码。

4 实现客户端例程

在这一步可以简单地编写一个main函数,如:(注意包含的头文件)

#include "calc.nsmap"

#include "soapcalcProxy.h" //该头文件已经包含了soapH.h

int main(void)

{

printf("very good!\n");

calcProxy service;

{

double result;

if(service.pow(2, 10, result) == SOAP_OK)

{

std::cout << "The value of 2^10 is " << result << std::endl;

}

}

return 0;

}

5 gcc编译客户端,生成可执行代码

    编译需要的文件有:第3步生成的所有文件、第4步编写的main函数所在的文件,以及gsoap目录下的stdsoap2.h和stdsoap2.cpp文件共9个文件。

如:calc.nsmap、soapC.cpp、soapH.h、soapStub.h、soapcalcProxy.cpp、soapcalcProxy.h、stdsoap2.cpp、stdsoap2.h、main.cpp。

(PS:.nsmap文件必须要在一个源文件中包含,像包含头文件一样)

参考网址:http://blog.csdn.net/houqd2012/article/details/44095511

 

<2>

以上是针对单个web server,下面讲解针对多个web server(下面以我自己做的项目为例来写的)。

1.首先,把gsoap的安装目录"...\gsoap_2.8.53\gsoap-2.8\gsoap\bin\win32\"下面的soapcpp2.exe和wsdl2h.exe2个可执行程序拷贝到当前工程目录,并且把"...\gsoap_2.8.53\gsoap-2.8\gsoap\import\"目录下的soap12.h拷贝到当前工程目录。

2.打开cmd命令工具,进入当前目录,执行wsdl.bat脚本(自己写的脚本,就是执行wsdl2h.exe命令,只是多执行几次,每次的web server地址不同而已,这里为了方便,不必每次敲多次命令),生成8个.h文件。

3.新建一个头文件test_wsdl.h,将8个头文件合并成一个头文件。(存在几个重复定义问题,具体问题在哪不明确,所以

直接执行第二个脚本文件soapcpp2.bat(也是自己写的,虽然只有一句,但是为了和上面wsdl2h.bat脚本的统一性,也使用脚本),会提示下载源码有错误,,这时根据提示的错误修改合并后的test_wsdl.h,一般错误都是重复定义问题,注释掉就可以)

4.继续第3步,直到没有error提示。

5.执行soapcpp2.bat脚本,会下载soapC.c、soapClient.c、soapH.h、soapStub.h和一些.nsmap文件,这些.nsmap文件内容都一样,新建一个文件test.nsmap代替这些.nsmap文件(这里看你自己,也可以使用其中的一个nsmap文件,我这里主要为了代码看起来让人易懂而已)。

6.要想通过编译,必须要"...\gsoap_2.8.53\gsoap-2.8\gsoap\"目录下的stdsoap2.c和stdsoap2.h,并且新建一个源文件必须包含test.nsmap文件。

7. 测试。

参考网址:http://blog.csdn.net/limiko/article/details/6103073#reply

 

<3>

以上过程都是在网上教程总结得来,但是在实际编程过程中又遇见新的问题,但是网上并没有给出相应的解释和解决方案。以下是所遇的问题和解决方案:

1. 在使用gsoap工具产生的接口函数,在成功调用后,并不能得到想要的xml格式的数据,只是得到web server对应接口的xml的<xs:schema ...> ...</xs:schema> 节点中间的部分值。怎么办?

在网上查找许久,也没找到相应的对策,也可能是我的搜查方式不对。但是在查找的过程中,在http://blog.csdn.net/yui/article/details/5767494 这篇博客中给了我启发,为什么这个结果结构体中有两个数据成员,当时猜想两个成员一个对应<xs:schema ...> ...</xs:schema> 节点数据,一个对应<diffgr:diffgram ...>...</diffgr:diffgram>节点数据。但是当时就猜想为什么这个得到的结构体含有两个成员,我这个为什么就一个成员?当时就想应该是使用wsdl2h.exe工具下载.h 文件的时候是不是漏了什么参数或者哪里没有设置好,然后开始研究wsdl2h.exe,但是没有结果。第二天,我就开始想,应该是服务器那边的问题(因为服务器那边是别人早就做好的,使用别的语言soap协议都没问题,所以不能更改),由于别的语言使用soap协议使用没问题,所以打破我的想法(虽然别的语言soap协议可以,但是我依然认为有可能是服务器那边有问题或者某开关项没打开)。就在这个时候准备放弃的时候,想到了,我们使用gsoap下载的.h头文件,也可以自己写,说明这个.h可以修改。所以我在代码中的结构体增加了一项

_XML  xsd__schema    1;   如图所示:

 

然后重新使用soapcpp2.exe工具下载源码,果然可以得到<xs:schema ...> ...</xs:schema> 节点数据和<diffgr:diffgram ...>...</diffgr:diffgram>节点数据。

 

2. 第二次又碰到soap代码问题,是在前后执行不同命名空间(这个命名空间不是c++的命名空间,是soap协议定义的命名空间)的接口函数,会出现第二次执行接口函数一直错误(排除传值错误的情况下),怎么办?

这个问题刚开始遇到,我还以为是我使用函数的方法出现了问题,所以试了好几下都没成功。然后我开始使用断点跟踪,一步一步跟踪到gsoap下载的源码里面,发现第二次进入到匹配命名空间的函数有问题(具体哪个判断不成立我忘记了,因为挺久的了,反正就是其中一个),如下图所示:

 

然后我单独测试这个url的接口,重新下载,运行时没有问题的,所以问题还是出现在命名空间,然后开始看soap的文档,文档上有处理类似的问题,但是不一样,结果还是不能成功,文档上介绍的是服务器端的解决方法。之后上司给我的提醒是(因为当时碰到这个问题比较棘手,问了他,他也帮我看了一下文档),在每次执行接口函数前,都调用一次设置命名空间的函数(soap协议内部函数,一般是不提供外部使用,我的理解)。如图所示:

 

(备注:该namespaces是在test.nsmap文件中定义。)

 

但是,还是存在一样的问题。然后我灵感一动,把namespace拆分成刚开始一个一个url下载soap API的时候的命名空间,每个命名空间都不一样(而现在合并test_wsdl.h下载soap协议源码的.nsmap文件里面的命名空间都一样),并且把存储命名空间的变量名也改成对应的url的名字(自己定义),但是这样编译就会出现一个问题:未找到namespaces定义。所以还要建一个nsmap文件,定义namespaces为空(或者其他命名空间都行),这个namespaces是第一次初始化soap结构体变量的需要赋的值,因为你每次执行接口函数都调用soap_set_namespaces()函数,所以命名空间又一次改变,所以第一次赋什么值不重要,但是要给一个值就行。

 

果然,程序通过编译,执行也成功。


但是最近在使用别的API的时候,发现一个新的问题。如下图,是gsoap工具自动产生的头文件部分


显然,这种情况跟上面不一样。再不改动情况下,生成源代码API,并且使用这个对应API会在运行的时候出错(前提正确调用API)。

解决办法:修改头文件如下图所示


修改后为“通用”的结构体。在此从新下载源码,运行则成功。

这篇算我真正意义上的第一篇博客,如果有什么没写清楚的地方或者什么写错的地方,希望广大网友给点意见,谢谢。

gSOAP编译工具提供了一个SOAP/XML 关于C/C++ 语言的实现,从而让C/C++语言开发web服务或客户端程序的工作变得轻松了很多。绝大多数的C++web服务工具包提供一组API函数类库来处理特定的SOAP数据结构,这样就使得用户必须改变程序结构来适应相关的类库。与之相反,gSOAP利用编译器技术提供了一组透明化的SOAP API,并将与开发无关的SOAP实现细节相关的内容对用户隐藏起来。   gSOAP的编译器能够自动的将用户定义的本地化的C或C++数据类型转变为符合XML语法的数据结构,反之亦然。这样,只用一组简单的API就将用户从SOAP细节实现工作解脱了出来,可以专注与应用程序逻辑的实现工作了。gSOAP编译器可以集成C/C++和Fortran代码(通过一个Fortran到C的接口),嵌入式系统,其他SOAP程序提供的实时软件的资源和信息;可以跨越多个操作系统,语言环境以及在防火墙后的不同组织。   gSOAP使编写web服务的工作最小化了。gSOAP编译器生成SOAP的代码来序列化或反序列化C/C++的数据结构。gSOAP包含一个WSDL生成器,用它   来为你的web服务生成web服务的解释。gSOAP的解释器及导入器可以使用户不需要分析web服务的细节就可以实现一个客户端或服务端程序。   下面是gSOAP的一些特点:   ×gSOAP编译器可以根据用户定义的C和C++数据结构自动生成符合SOAP的实例化代码。   ×gSOAP支持WSDL 1.1, SOAP 1.1, SOAP 1.2, SOAP RPC 编码方式以及 literal/document 方式.   ×gSOAP是少数完全支持SOAP1.1 RPC编码功能的工具包,包括多维数组及动态类型。比如,一个包含一个基类参数的远程方法可以接收客户端   传来的子类实例。子类实例通过动态绑定技术来保持一致性。   ×gSOAP 支持 MIME (SwA) 和 DIME 附件包。   ×gSOAP是唯一支持DIME附件传输的工具包。它允许你在保证XML可用性的同时能够以最快的方式(流方式)传递近乎无大小限制的二进制数据   。   ×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)。   ×gSOAP 支持 HTTP/1.0, HTTP/1.1 保持连接, 分块传输及基本验证。   ×gSOAP 支持 SOAP 单向消息。   ×gSOAP 包含一个 WSDL 生成器,便于web服务的发布。   ×gSOAP 包含一个WSDL解析器(将WSDL转换为gSOAP头文件),可以自动化用户客户端及服务端的开发。   ×生成可以单独运行的web服务及客户端程序。   ×因为只需要很少内存空间,所以可以运行在类似Palm OS, Symbian, Pocket PC的小型设备。   ×适用于以C或C++开发的web服务。   ×跨平台Windows, Unix, Linux, Mac OS X, Pocket PC, Palm OS, Symbian等。   ×支持序列化程序的本地化C/C++数据结构。   ×可以使用输入和输出缓冲区来提高效率,但是不用完全消息缓冲来确定HTTP消息的长度。取而代之的是一个三相序列化方法。这样,像64位   编码的图像就可以在小内存设备(如PDA)以DIME附件或其他方式传输。   ×支持C++单继承,动态绑定,重载,指针结构(列表、树、图、循环图,定长数组,动态数组,枚举,64位2进制编码及16进制编码)。   ×不需要重写现有的C/C++应用。但是,不能用unions,指针和空指针来作为远程方法调用参数的数据结构元素。   ×三相编组:1)分析指针,引用,循环数据结构;2)确定HTTP消息长度;3)将数据序列化位SOAP1.1编码方式或用户定义的数据编码方式。   ×双相编组:1)SOAP解释及编码;2)分解“forward”指针(例如:分解SOAP的href属性)。   ×完整可定制的SOAP错误处理机制。   ×可定制的SOAP消息头处理机制,可以用来保持状态信息   2 gSoap2.2版与gSOAP 2.1版(或以前版本)的不同   如果你是从2.1版升级到2.2或以后版本,请注意这些变化。   为了能够分离传输、内容编码、映射的接收/发送设置,改变了运行时选项及标志。这些标志分布再四个类:传输(IO),内容编码(ENC   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值