阅读目录
概念定义
开发环境
客户端开发步骤
小结
WebService是一种跨编程语言和跨操作系统平台的远程调用技术。服务端向外界暴露一个可以被客户端通过网络调用的API。客户端调用API的过程实际上可以看作调用一个函数,不同点就是该函数是远程的。服务端和客户端调用关系如图1所示。
图1 WebService示意图
WebService中涉及到WSDL、SOAP的概念。
WSDL:WebService描述语言,是一个用于精确描述Web服务的XML文档。它描述了WebService接口信息,比如入参,出参,接口名称等,当我们需要调用第三方WebService接口时,我们必须要知道WSDL地址。WebService可以有两种方式来暴露他的WSDL地址:注册到UDDI中或者直接告诉调用者地址。
SOAP: 简单对象访问协议,是一种轻量的、简单的、基于XML的协议,它被设计成在WEB上交换结构化的和固化的信息。SOAP 是基于 XML 的简易协议,可使应用程序在 HTTP 之上进行信息交换。
基本概念介绍完毕,本文详细介绍如何使用C++开发一个WebService客户端进行API调用,以获取天气预报为例。
操作系统:Win10 64位 编程环境:VC6.0、SDK2003 开发工具:gsoap_2.8.95 |
二、开发环境
gSOAP编译工具提供了一个SOAP/XML 关于C/C++ 语言的实现,从而让C/C++语言开发web服务或客户端程序的工作变得轻松了很多。绝大多数的C++web服务工具包提供一组API函数类库来处理特定的SOAP数据结构,这样就使得用户必须改变程序结构来适应相关的类库。与之相反,gSOAP利用编译器技术提供了一组透明化的SOAP API,并将与开发无关的SOAP实现细节相关的内容对用户隐藏起来。(来自百度)
三、客户端开发步骤
天气预报的WebService WSDL地址为:
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl |
- 使用gSOAP的wsdl2h.exe和soapcpp2生成客户端使用的C++文件。
- 下载并解压gsoap_2.8.95.zip.
- 在gsoap_2.8.95\gsoap-2.8\gsoap\bin\win32下新建一个字符转换规则文件wsmap.dat,内容如下,可以更好的支持中文。转换规则可参考gsoap_2.8.95\gsoap-2.8\gsoap\typemap.dat。
xsd__string = | std::wstring | wchar_t*
- 用 wsdl2h.exe 将wsdl文件或者wsdl网址翻译成为.h文件,实现数据绑定接口。启动cmd,进入gsoap_2.8.95\gsoap-2.8\gsoap\bin\win32目录下,调用wsdl2h.exe生成头文件接口定义,命令及参数解释如下:
命令: wsdl2h -o WeatherSoap.h -t wsmap.dat http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl wsdl2h参数说明如下: -o 文件名,指定输出头文件 -n 命名空间前缀 代替默认的ns -c 产生纯C代码,否则是C++代码 -s 不要使用STL代码 -t 文件名,指定type map文件,默认为typemap.dat -e 禁止为enum成员加上命名空间前缀
- soapcpp2.exe为接口文件中声明的每种可序列化C / C ++类型生成一组函数。把\gsoap_2.8.95\gsoap-2.8\gsoap\import路径下的soap12.h 和stlvector.h复制到win32目录下,或者通过-l指定import路径。使用soapcpp2解析WeatherSoap.h,生成存根程序,命令及参数解释如下:
命令: soapcpp2 -i -C WeatherSoap.h soapcpp2参数说明: -C 仅生成客户端代码 -S 仅生成服务器端代码 -L 不要产生soapClientLib.c和soapServerLib.c文件 -c 产生纯C代码,否则是C++代码(与头文件有关) -I 指定import路径(此项是必要的,因前面为指定-s) -x 不要产生XML示例文件 -i生成C++包装,客户端为xxxxProxy.h(.cpp),服务器端为xxxxService.h(.cpp) -j生成C ++代理类 -CL指示客户端(非libs)
- 创建工程进行客户端代码实现。
- VC6.0创建工程。
- 将生成的C++文件引入工程,将解析出来的soapC.cpp、soapH.h、soapStub.h、soapWeatherWebServiceSoapProxy.cpp、soapWeatherWebServiceSoapProxy.h、WeatherWebServiceSoap.nsmap、stdsoap2.cpp stdsoap2.h文件引入工程,即可调用。(注意:工程一定要引入WeatherWebServiceSoap.nsmap,不然会有命名空间编译出错的问题。)
soapC.cpp 指定数据结构的序列化器和反序列化器 soapH.h 主 Header 文件,所有客户机和服务源代码都要将其包括在内 soapStub.h 从输入 Header 文件生成的经过修改且带标注的 Header 文件 soapWeatherWebServiceSoapProxy.cpp soapWeatherWebServiceSoapProxy.h 这两个文件是客户端代码的一个简单封装,它封装了底层通信。客户端通过实例化该类进行调用。 stdsoap2.cpp 运行时 C++ 库,带 XML 解析器和运行时支持例程 stdsoap2.h 为stdsoap2.cpp 运行时库的 Header 文件 WeatherWebServiceSoap.nsmap 命名空间定义,客户端需要包含它
- 编译,有几处编译错误,例如VC6.0不支持C99标准,因此wctomb_s 处编译错误,可修改为VC6.0支持的wcstombs,同时根据该方法修正参数。_strtoui64增加声明和实现。根据编译过程中碰到的问题,修改代码即可。
- 参考WSDL查看说明,以根据城市名称获取天气getWeatherbyCityName为例,根据如下WSDL中的描述。输入参数为城市中文名称或者城市代码,输出为含23个元素的一维数组,包括查询的省份、城市、城市代码、更新时间、气温等信息,具体排列顺序参考如下WSDL中的描述。
wsdl:operation name="getWeatherbyCityName"> <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"><br><h3>根据城市或地区名称查询获得未来三天内天气情况、现在的天气实况、天气和生活指数</h3><p>调用方法如下:输入参数:theCityName = 城市中文名称(国外城市可用英文)或城市代码(不输入默认为上海市),如:上海 或 58367,如有城市名称重复请使用城市代码查询(可通过 getSupportCity 或 getSupportDataSet 获得);返回数据: 一个一维数组 String(22),共有23个元素。<br />String(0) 到 String(4):省份,城市,城市代码,城市图片名称,最后更新时间。String(5) 到 String(11):当天的 气温,概况,风向和风力,天气趋势开始图片名称(以下称:图标一),天气趋势结束图片名称(以下称:图标二),现在的天气实况,天气和生活指数。String(12) 到 String(16):第二天的 气温,概况,风向和风力,图标一,图标二。String(17) 到 String(21):第三天的 气温,概况,风向和风力,图标一,图标二。String(22) 被查询的城市或地区的介绍 <br /><a href="http://www.webxml.com.cn/images/weather.zip">下载天气图标<img src="http://www.webxml.com.cn/images/download_w.gif" border="0" align="absbottom" /></a>(包含大、中、小尺寸) <a href="http://www.webxml.com.cn/zh_cn/weather_icon.aspx" target="_blank">天气图例说明</a> <a href="http://www.webxml.com.cn/files/weather_eg.zip">调用此天气预报Web Services实例下载</a> (VB ASP.net 2.0)</p><br /></wsdl:documentation> <wsdl:input message="tns:getWeatherbyCityNameSoapIn"/> <wsdl:output message="tns:getWeatherbyCityNameSoapOut"/> </wsdl:operation>
- 编写客户端调用代码,如下所示,可获取输出信息。
WeatherWebServiceSoapProxy proxy("http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl",SOAP_C_UTFSTRING); soap_init(&proxy); ns1__getWeatherbyCityName InputString; InputString.soap = &proxy; InputString.theCityName = _T("北京"); ns1__getWeatherbyCityNameResponse response; int nResult = proxy.getWeatherbyCityName(&InputString,response); if (nResult==0) { std::vector<std::wstring> vectorTemp = response.getWeatherbyCityNameResult->string; }
- 运行,输入城市北京,得到输出结果,按数组顺序排列,部分内容已简化。
直辖市 北京 54511 54511.jpg 2021/1/3 9:35:54 -9℃/-1℃ 1月3日 多云 南风转北风小于3级 1.gif 1.gif 今日天气实况:……。 -10℃/0℃ 1月4日 多云转晴 北风3-4级转小于3级 1.gif 0.gif -10℃/-1℃ 1月5日 晴转多云 南风小于3级转北风3-4级 0.gif 1.gif 北京位于华北平原西北边缘……。
四、小结
WebService作为一种跨平台的技术应用,本质上是服务器端整出一些资源可以让客户端应用访问(获取数据),集团内部使用较多。例如,服务器端提供公司职员信息,客户端通过调用WebService接口获取人员信息等。
C#和JAVA开发WebService相对于C/C++来说较为方便,而gSOAP工具使得C/C++开发WebService成为可能。gSOAP工具可以使得开发人员在不必关心协议内部实现,更多的关注服务器端方法的实现以及客户端方法的调用。
WebService的测试可以使用soapUI工具,该工具开源,soapUI PRO为商业非开源版本。可以通过soapUI工具测试服务器接口是否正常。