因为项目中需要使用WebService,所以将webservice的有关东西温故了一下。以前采用C#,这几乎不成什么问题,毕竟C#与WebService几乎是同时火起来的,所以C#天然地支持webservice就不奇怪了。Java的情况大致与C#一样,C/C++就不同了,还好有gSOAP,就用一下吧。
gSOAP是一个开发SOAP和XML应用(它们组成了webservice)的工具,在英文中叫toolkit。它是跨平台的,webservice的客户端和服务器端,都可以用它来辅助开发。它主要的功能(特征)如下:
目前gSOAP的版本是2.8.12,作者认为,gSOAP的组织结构以及使用的方便性,在开源项目中是比较好的。
在应用中,我们首先要应用它的两个工具: soapcpp2和 wsdl2h。所幸的是这个两个工具在gSOAP包中已经被编译生成(bin目录下),所以我们只要拿来用即可,gSOAP使用的方便性就体现出来了。另一个方便性是它的源文件个数较少,如果我们不去研究,少的文件个数包含在我们的工程中,也减少了维护的成本。
Soapcpp2是一个根据.h文件生成若干支持webservice的代码生成工具,生成的代码文件包括webservice客户端和服务器的实现框架,XML数据绑定等,具体说明如下:
文件 |
描述 |
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 |
命名空间的定义,对命名空间不敏感的,不用关注。 |
使用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++ 类型信息 |
该工具是可以根据输入的wsdl或XSD或URL,产生相应的C/C++形式的.h(不能直接引用),供soapcpp2使用。
wsdl2h主要的运行选项如下:
选项 |
描述 |
-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代替) |
-? |
显示帮助信息 |
我们开发webservice应用,大致有两个方向:
1. API接口固定,不关心底层的通讯,将SOAP作为应用层协议
此时,我们先定义接口,编写好.h文件,运行soapcpp2生成出相应的代码,对服务器端,修改XXXService文件,实现业务逻辑,对客户端,修改XXXProxy文件,实现业务逻辑。
2. 通讯协议固定(当然需要基于XML的)或只有wsdl,将SOAP作为“传输层”协议
此时,我们必须根据通讯协议或wsdl生成相应的C/C++类型的.h文件,如果需要我们自己编写wsdl,则需要一点其相关知识,不过我们可以用C#等生成一个简单的wsdl,照猫画虎即可。运用wsdl2h,我们可以生成.h文件,有了.h后,按上面的步骤继续。
(待续,下一节给出实例)