gsoap是C/C++开发WebService的框架。
gsoap提供了wsdl2h和soapcpp这两个工具用于生成框架代码。
wsdl2h
顾名思义,这是将.wsdl文件生成.h文件的工具。wsdl(Web Service Define Language)描述了WebService方法。但只有WebService的描述还不够,还要有实现WebService的机制,于是soap就派上了用场。soap(Simple Object Access Protocol)基于HTTP协议,它定义了WebService双方的通信协议。gsoap内部实现了soap协议,gsoap能够根据wsdl描述生成通信框架代码,于是我们只需要提供wsdl来说明将要实现哪些WebService,剩下的工作就交由gsoap来做了。
现如果你对wsdl还不了解,可参考http://www.w3school.com.cn/wsdl/wsdl_intro.asp。
以下wsdl定义了一个通过昵称获取个人信息的WebService,文件命名为user.wsdl。
1 <?xml version="1.0" encoding="utf-8"?>
2 <definitions name="User"
3 targetNamespace="www.homesilk.net/service/user"
4 xmlns="http://schemas.xmlsoap.org/wsdl/"
5 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
6 xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
7 xmlns:SOAP="http://schemas.xmlsoap.org/wsdl/soap/"
8 xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
9 xmlns:tns="www.homesilk.net/service/user"
10 >
11 <message name="nickname">
12 <part name="nickname" type="xsd:string" />
13 </message>
14 <message name="user">
15 <part name="nickname" type="xsd:string" />
16 <part name="name" type="xsd:string" />
17 <part name="sex" type="xsd:int" />
18 <part name="birthday" type="xsd:string" />
19 </message>
20 <portType name="UserPortType">
21 <operation name="getUser">
22 <input message="tns:nickname" />
23 <output message="tns:user" />
24 </operation>
25 </portType>
26 <binding name="User" type="tns:UserPortType">
27 <SOAP:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
28 <operation name="getUser">
29 <input>
30 <SOAP:body use="literal"/>
31 </input>
32 <output>
33 <SOAP:body use="literal"/>
34 </output>
35 </operation>
36 </binding>
37 </definitions>
然后运行./wsdl2h -N user -c user.wsdl,会生成user.h文件。
-N user 指定了service前缀(命名空间)为user,如果你使用-n user,那么service前缀将会变为user1,因为-n指定的是命名空间前缀而不是命名空间。
-c指定生成C语言风格的头文件。
message节点、portType节点、binding节点均为wsdl定义的节点。
message描述了传递的参数,所有的输入(输出)信息组合为一个message,本例中输入信息只有一个nickname,输出信息有四个部分。
当然你可能会想能不能将输入(输出)信息分为不同的message,答案是不行的,原因在于portType这个节点下的operation至多只接收两个参数,在operation中你没有多余的空间放置额外的message。
portType节点指定了不同message的组合,它和函数指针的功能类似,指定了输入、返回值,也即是portType已经决定了service接口。
binding节点指定了提供给外界的接口,以及信息传输过程中使用的协议,信息编码。
soapcpp2
通过wsdl2h我们产生了user.h,接下来就该用这个头文件生成WebService框架了。
运行./soapcpp2 -c user.h,
生成了
User.nsmap
soapH.h、soapStub.h
soapC.c、soapClient.c、soapClientLib.c、soapServer.c、soapServerLib.c
User.getUser.req.xml、User.getUser.res.xml
User.nsmap的内容如下
1
2 #include "soapH.h"
3 SOAP_NMAC struct Namespace namespaces[] =
4 {
5 {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/", "http://www.w3.org/*/soap-envelope", NULL},
6 {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/", "http://www.w3.org/*/soap-encoding", NULL},
7 {"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance", NULL},
8 {"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema", NULL},
9 {"user", "www.homesilk.net/service/user", NULL, NULL},
10 {NULL, NULL, NULL, NULL}
11 };
我们在user.wsdl中指定了命名空间:SOAP-ENV、SOAP-ENC、xsd在这里都出现了,并且还多了xsi、user这两个命名空间,xsi是gsoap自动添加的,而user则对应于我们运行./wsdl2h -N user -c user.wsdl时通过-N指定的命名空间。SOAP-ENV、SOAP-ENC是soap协议必须的参数,xsi、xsd在解析传递的参数时起到了作用。
User.getUser.req.xml是service请求的xm格式,User.getUser.req.xml是service响应的xm格式。