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)。

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


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

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

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值