2019独角兽企业重金招聘Python工程师标准>>>

gSOAP是一个绑定SOAP/XML到C/C++语言的工具,使用它可以简单快速地开发出SOAP/XML的服务器端和客户端。由于gSOAP具有相当不错的兼容性,通过gSOAP,我们就可以调用由Java, .Net, Delhpi, PHP等语言开发的SOAP服务,或者向它们提供SOAP服务。

gSOAP是一个绑定SOAP/XML到C/C++语言的工具,使用它可以简单快速地开发出SOAP/XML的服务器端和客户端。由于 gSOAP具 有相当不错的兼容性,通过gSOAP,我们就可以调用由Java, .Net, Delhpi, PHP等语言开发的SOAP服务,或者向它们提供SOAP服务。

gSOAP的主页是:

http://sourceforge.net/projects/gsoap2

下载解压后,可以在gsoap/bin/win32里 找到wsdl2h.exe和soapcpp2.exe(另外还有linux和mac版本)。

  • wsdl2h.exe的作用是根据WSDL生成C/C++风格的头 文件

  • soapcpp2.exe的作用是根据头文件自动生成调用远程 SOAP服务的客户端代码(称为存根:Stub)和提供SOAP服务的框架代码(称为框架:Skeleton),另外它也能从头文件生成WSDL文件。

gsoap/stdsoap2.cpp则是gSOAP的核心代码,要使用 gSOAP只要在项目里包含这个文件以及由soapcpp2.exe生成的代码即可。另外还有个stdsoap2.c,内容与stdsoap2.cpp一 模一样,用于纯C项目。

gSOAP两大工具的用法

从WSDL中产生头文件

用法:

wsdl2h -o 头文件名 WSDL文件名或URL

wsdl2h常用选项

  • -o 文件名,指定输出头文件

  • -n 名空间前缀 代替默认的ns

  • -c 产生纯C代码,否则是C++代码

  • -s 不要使用STL代码

  • -t 文件名,指定type map文件,默认为typemap.dat

  • -e 禁止为enum成员加上名空间前缀

type map文件用于指定SOAP/XML中的类型与C/C++之间的转换规则,比如在wsmap.dat里写

xsd__string = | std::wstring | wchar_t*

那么SOAP/XML中的string将转换成std::wstring或wchar_t*,这样能更好地支持中文。

例:

wsdl2h -o ayandy.h /-n ay -t wsmap.dat /http://www.ayandy.com/Service.asmx?WSDL

从http://www.ayandy.com/Service.asmx?WSDL 生成ayandy.h文件,名空间为ay,使用wsmap.dat指定的转换规则。

wsdl2h生成的头文件里的变量、类型等名称的前面都会加上名空间前缀,以两个下划线分隔。如上面的命令生成的头文件,有这样的定 义:

  1. class ay1__ArrayOfString;

  2. enum ay1__theDayFlagEnum

  3. {

  4. ay1__theDayFlagEnum__Today,

  5. ay1__theDayFlagEnum__Tomorrow,

  6. ay1__theDayFlagEnum__theDayafterTomorrow,

  7. };

前面的ayandy1__的是名空间前缀,用以防止名称冲突。 wsdl2h的-n选项可以改变这个名空间前缀(默认为ns)。对于枚举ay1__theDayFlagEnum内 的成员,如果嫌它太长的话,可以用-e命令选项禁止加入名空间前缀。

从头文件生成存根(stub)和框架(Skeleton)源文件

编写SOAP程序除了头文件是不够的,还要有连接、通信、XML解析、序列/反序列化等工作。gSOAP提供的socapcpp2.exe就 是用于从头文件中生成这些代码的,我们只要关心真正的业务逻辑就行了。

用法

soapcpp2 头文件

例:

soapcpp2 ayandy.h

将生成下面这些文件

  • soapStub.h    // soap的存根文件,定义了ayandy.h里对应的远程调用模型

  • soapC.c soapH.h // soap的序列和反序列代码,它已经包含了soapStub.h,服务器端与客户端都要包含它

  • soapClient.c soapClientLib.c // 客户端代码,soapClientLib.c文件则只是简单地包含soapClient.c和soapC.c

  • soapServer.c soapServerLib.c // 服务器端代码,soapServerLib.c文件则只是简单地包含soapServer.c和soapC.c

  • ServiceSoap.nsmap ServiceSoap12.nsmap // 名空间定义,服务器端与客户端都要包含它

  • soapServiceSoapProxy.h soapServiceSoap12Proxy.h // 客户端的C++简单包装(如果头文件是纯C代码,这两个文件就不会生成)

综上所述

  • 如果编写服务器端,项目里应该加入soapServerLib.c,代码里包含头文件soapH.h

  • 如果编写客户端,项目里应该加入soapClientLib.c,代码里包含头文件SoapH.h(或xxxxProxy.h)

  • 当然,还要加入gsoap库里的stdsoap2.cpp文件(如果是写C代码,则加入stdsoap2.c)

如果看到soapcpp2提示:”Critical error: #import: Cannot open file "stlvector.h" for reading.“, 那是因为我们的头文件使用了STL(wsdl2h 没用-s选项),这时要使用-I选项指定gSOAP的 import文件路径,这个路径是"$gsoap/gsoap/import":

soapcpp2 ayandy.h -I D:/gsoap-2.7/gsoap/import

soapcpp2常用选项

  • -C 仅生成客户端代码

  • -S 仅生成服务器端代码

  • -L 不要产生soapClientLib.c和soapServerLib.c文件

  • -c 产生纯C代码,否则是C++代码(与头文件有关)

  • -I 指定import路径(见上文)

  • -x 不要产生XML示例文件

  • -i 生成C++包装,客户端为xxxxProxy.h(.cpp),服务器端为xxxxService.h(.cpp)。

编写SOAP客户端

下面将演示使用gSOAP到网上取得天气预报,互联网上有不少网站提供SOAP服务,比如Google提供的搜索API(现在已不再提 供新的License Key了),不少博客提供的API等。这里介绍一个提供天气预报服务的SOAP服务,地址是http://www.ayandy.com

它提供了三个函数

  • getSupportCity 查询本天气WebService支持的城市信息。

  • getSupportProvince 查询本天气 WebService支持的省份信息。

  • getWeatherbyCityName 根据城市名称获得天 气情况。

它的WSDL地址是http://www.ayandy.com/Service.asmx?WSDL

现在,我们编写一个客户端去调用getWeatherbyCityName来 取得天气情况

1. 从WSDL得到头文件

wsdl2h -o ayandy.h http://www.ayandy.com/Service.asmx?WSDL

2. 从头文件得到存根(Stub)源文件

soapcpp2 -i -C -x ayandy.h -ID:/gsoap-2.7/gsoap/import

命令选项注释:

  • -i 直接使用C++包装类

  • -x 不要生成一堆看了就恶心的xml

  • -C 只生成客户端相关代码

  • -I 指定import路径

3. 建立新项目

把gsoap库里的stdsoap2.cpp文件,以及上一步生成的soapServiceSoapProxy.cpp和soapC.cpp都加入到项 目。

设置加入的这三个文件为不使用预编译头。

4. 编写代码

由于参数及回传的数据都是中文,所有让gSOAP使用UTF8方式传送以防止乱码。

  1. #include <iostream>

  2. #include <string>

  3. #include "soapServiceSoapProxy.h"

  4. #include& nbsp;"ServiceSoap.nsmap" //表忘了名空间定义

  5. using namespace std;

  6. // 宽 字符转UTF8

  7. string EncodeUtf8(wstring in)

  8. {

  9. string s(in.length()*3+1,' ');

  10. size_t len = ::WideCharToMultiByte(CP_UTF8, 0,

  11. in.c_str(), in.length(),

  12. &s[0], s.length(),

  13. NULL, NULL);

  14. s.resize(len);

  15. return s;

  16. }

  17. // UTF8 转宽字符

  18. wstring DecodeUtf8(string in)

  19. {

  20. wstring s(in.length(), _T(' '));

  21. size_t len = ::MultiByteToWideChar(CP_UTF8, 0,

  22. in.c_str(), in.length(),

  23. &s[0], s.length());

  24. s.resize(len);

  25. return s;

  26. }

  27. int main(int argc, char* argv[])

  28. {

  29. ServiceSoapProxy gs(SOAP_C_UTFSTRING);

  30. _ns1__getWeatherbyCityName cityname;

  31. _ns1__getWeatherbyCityNameResponse resp;

  32. string strCityName = EncodeUtf8(L"苏州");

  33. cityname.theCityName = &strCityName;

  34. cityname.theDayFlag = ns1__theDayFlagEnum__Tomorrow;

  35. if(gs.getWeatherbyCityName(&cityname, &resp) == SOAP_OK)

  36. {

  37. ns1__ArrayOfString *aos = resp.getWeatherbyCityNameResult;

  38. wcout.imbue( std::locale("chs") ); //指定输出为中文

  39. for(vector<string>::iterator

  40. itr=aos->string.begin(), itr_end = aos->string.end();

  41. itr!=itr_end; ++itr)

  42. wcout << DecodeUtf8(*itr) << endl;

  43. }

  44. return 0;

  45. }

上面的代码花了一半在UTF8编码转换上,如果参数里没有中文的话,代码会简化很多:

  1. ServiceSoapProxy gs;

  2. _ns1__getWeatherbyCityName cityname;

  3. _ns1__getWeatherbyCityNameResponse resp;

  4. string strCityName("苏州");

  5. cityname.theCityName = &strCityName;

  6. cityname.theDayFlag = ns1__theDayFlagEnum__Tomorrow;

  7. if(gs.getWeatherbyCityName(&cityname, &resp) == SOAP_OK)

  8. {

  9. ns1__ArrayOfString *aos = resp.getWeatherbyCityNameResult;

  10. for(vector<string>::iterator

  11. itr=aos->string.begin(), itr_end = aos->string.end();

  12. itr!=itr_end; ++itr)

  13. cout << *itr << endl;

  14. }

但是这个代码应用到中文字符串时,会发现返回的是一堆乱码,gSOAP有两种方式支持它:

  1. 使用宽字符集,如用前文演示的type map文件来转换字符串为std::wstring。

  2. 使用UTF8传送字符串,这个例子就是使用的这个方式:首先,定义ServiceSoapProxy gs的传送模式为SOAP_C_UTFSTRING;然后输入时把字符串转换成UTF8,得到输出时把UTF8转换回来。

使用UTF8时还要注意一点,如果使用纯C调用,那么应该这样设置UTF8调用:

  1. soap sp;

  2. soap_init(&sp);

  3. soap_set_mode(&sp, SOAP_C_UTFSTRING);

  4. sp.mode |= SOAP_C_UTFSTRING; //关键

也许是gSOAP的bug吧,soap_set_mode只 设置了sp.imode和sp.omode两个成员,却没有设置sp.mode。跟踪代码可以发现从服务器传回数据后,gSOAP是根据sp.mode来 决定是否使用UTF8转换的。

编写SOAP服务器

现在,我们自己动手写一个天气预报服务,当然,是乱报的啦,呵呵。

1.这次,我们尝试使用宽字符集的方式来支持中文

写一个wsmap.dat文件,里面写上:xsd__string = | std::wstring | std::wstring*

2.从WSDL生成头文件

wsdl2h.exe -o ayandy.h -t wsmap.dat -e http://www.ayandy.com/Service.asmx?WSDL

命令选项注释:

  • -o ayandy.h 生成ayandy.h头文件

  • -t wsmap.dat 根据wsmap.dat规则转换数据类型

  • -e 枚举成员不要有长长的名空间前缀

3.从头文件生成服务器框架代码

soapcpp2 ayandy.h -i -x -S -I D:/Code/libs/gsoap-2.7/gsoap/import

命令选项注释

  • -S 仅生成服务器框架代码

4.新建项目

把gsoap库里的stdsoap2.cpp文件,以及上一步生成的soapServiceSoapService.cpp和soapC.cpp都加入到 项目。

设置加入的这三个文件为不使用预编译头。

5.编写代码

打开soapcpp2生成的soapServiceSoapService.h文件,在ServiceSoapService类定义里 会看到这样几行字:

  1. ///

  2. /// Service operations (you should define these):

  3. ///

它后面的几个方法是要我们自己实现它的,先看代码吧:

  1. #include "soapServiceSoapService.h"

  2. #include "ServiceSoap.nsmap"

  3. /// Web service operation 'getWeatherbyCityName' (returns error code or SOAP_OK)

  4. int ServiceSoapService::getWeatherbyCityName(

  5. _ns1__getWeatherbyCityName *ns1__getWeatherbyCityName,

  6. _ns1__getWeatherbyCityNameResponse *ns1__getWeatherbyCityNameResponse)

  7. {

  8. if(*(ns1__getWeatherbyCityName->theCityName) != L"苏州") returnSOAP_USER_ERROR;

  9. ns1__ArrayOfString * aos = soap_new_ns1__ArrayOfString(this, -1);

  10. aos->string.push_back( std::wstring() ); //第0个空着

  11. if(ns1__getWeatherbyCityName->theDayFlag != Tomorrow)

  12. {

  13. aos->string.push_back( L"我只知道明天天气,其它的不要问我!" );

  14. }

  15. else

  16. {

  17. aos->string.push_back( L"有日食,不过下大雨,哈哈,气死你!" );

  18. aos->string.push_back( L"下雨当然有风啦,多大我也不知道" );

  19. }

  20. ns1__getWeatherbyCityNameResponse->getWeatherbyCityNameResult = aos;

  21. return SOAP_OK;

  22. }

  23. /// Web service operation 'getSupportProvince' (returns error code or SOAP_OK)

  24. int ServiceSoapService::getSupportProvince(

  25. _ns1__getSupportProvince *ns1__getSupportProvince,

  26. _ns1__getSupportProvinceResponse *ns1__getSupportProvinceResponse)

  27. {

  28. return SOAP_OK;

  29. }

  30. /// Web service operation 'getSupportCity' (returns error code or SOAP_OK)

  31. int ServiceSoapService::getSupportCity(

  32. _ns1__getSupportCity *ns1__getSupportCity,

  33. _ns1__getSupportCityResponse *ns1__getSupportCityResponse)

  34. {

  35. return SOAP_OK;

  36. }

  37. int main(int argc, char* argv[])

  38. {

  39. ServiceSoapService sev;

  40. return sev.run(8888);//本机8888端口

  41. }

编译,运行,现在我们的本机8888端口开始提供天气预报的SOAP服务了。

修改之前的客户端,在main()里第一行

  1. ServiceSoapProxy gs(SOAP_C_UTFSTRING);

后面加上:

  1. gs.soap_endpoint="http://localhost:8888";

运行这客户端后可以就看到我们提供的优质服务了:)

本例中getWeatherbyCityName方 法里的ns1__getWeatherbyCityNameResponse参 数用于返回数据,它的getWeatherbyCityNameResult成 员是由我们来申请内存的,这个内存应该用“soap_new_ 类名”来取得,这些申请函数可以从soapH.h里找到,如本例的soap_new_ns1__ArrayOfString。

  • 第一个参数是soap类型,它是ServiceSoapService的父类型,也是gSOAP中最重要的类型。

  • 第二个指定申请的个数,指定为-1表示只生成一个,否则生成一个指定数目的数组。

转载于:https://my.oschina.net/starmier/blog/204296

用gSOAP开发Web Service程序相关推荐

  1. 使用Axis开发Web Service程序

    今天是感恩节,差点又要在公司加班了.好在Web Service程序并不是特别难搞,下午终于在eclipse下调通过了,正确产生了服务器端和客户端的Java代码,apache的东西的确很不错. 说道We ...

  2. Linux下用gSOAP开发Web Service服务端和客户端程序(一)

    1.功能说明: 要开发的Web Service功能非常简单,就是一个add函数,将两个参数相加,返回其和. 2.C版本的程序: (1)头文件:SmsWBS.h,注释部分不可少,url部分的IP必须填写 ...

  3. JAVA开发Web Service几种框架介绍

    在讲Web Service开发服务时,需要介绍一个目前开发Web Service的几个框架,分别为Axis,axis2,Xfire,CXF以及JWS(也就是前面所述的JAX-WS,这是Java6发布所 ...

  4. 使用 python 开发 Web Service

    使用 python 开发 Web Service Python 是一种强大的面向对象脚本语言,用 python 开发应用程序往往十分快捷,非常适用于开发时间要求苛刻的原型产品.使用 python 开发 ...

  5. Java开发Web Service的简介

    随着异构系统互联需求的不断增加,Web Service的重要性也日益彰显出来.凭借Web Service,我们可以实现基于不同程序语言开发的项目之间的互联互通,Web Service也是面向服务的架构 ...

  6. .NET使用VS2010开发Web Service

    Web Service是一个面向服务的架构(SOA),不依赖于语言,不依赖于平台,可以实现不同的语言间的相互调用,通过Internet进行基于Http协议的网络应用间的交互.基于.NET平台,可以使用 ...

  7. 用eclipse europa开发web service服务 - 东写西读终见大海无量 - JavaEye技术网站

    用eclipse europa开发web service服务 eclipse europa自带web工具.我们可以使他生成动态web程序.但是在默认情况下,生成的动态默认程序是不包含web servi ...

  8. Delphi开发Web Service初探

    简介:"网络就是计算机,软件就是服务"的思想已经逐步深入人心.由于Web Services能够通过网络把服务直接递送给终端用户,而且由众多主流厂商所支持和描绘的美好前景也让我们心动 ...

  9. [图解教程]Axis2与Eclipse整合开发Web Service之二:WSDL逆向生成服务端

    [图解教程]Axis2与Eclipse整合开发Web Service之二:WSDL逆向生成服务端 一般开发Web Service,是选写服务端,再根据生成的WSDL文件生成客户端.看过一本SOA的书中 ...

最新文章

  1. 你需要启用steam社区界面功能以进行购买_绝地求生购买衣服方法
  2. Leetcode 每日一题 40 组合2
  3. boost::fusion::erase用法的测试程序
  4. python2.7与3.7脚本转换_python 2.7 - python 3.7 升级记录
  5. BZOJ2042 : [2009国家集训队]Will的烦恼
  6. HTML5基础网页设计(加代码CSS)
  7. sql server的增删改查语句
  8. gps l1带宽_请问GPS带宽是多少?
  9. python绘制语谱图(不掉包实现)
  10. Cannot find entry: /target/m2e-wtp/web-resources
  11. unity android 触屏,Unity 移动端触摸屏操作
  12. 给大家推荐一个软件:视频广告过滤大师
  13. linux中pid gid tgid tid的区别和联系
  14. oracle获取当前年上一年时间,Oracle获取一周前,一个月前,一年前的日期
  15. MackDown MAC版添加本地图片
  16. 小米 红米NOTE5 解BL锁教程 申请BootLoader解锁教程
  17. Android开发应用案例——简易计算器(附完整源码)
  18. 我英语不好,能学编程吗?
  19. 【NOIP2018模拟赛2018.10.22】pets
  20. python变成拍照搜题软件_2020年中国大学MOOC的APP用Python玩转数据作业答案

热门文章

  1. springboot整合通用mapper操作数据库
  2. java运输_JAVA-基础-方法
  3. Java高并发编程详解系列-ThreadGroup介绍
  4. QEMU多进程(Multi-process QEMU)及vfio-user应用
  5. 栈的基本操作(数组/链表)
  6. Hexo+NexT搭建博客笔记
  7. 【拓扑排序】确定比赛名次
  8. vue2之对象属性的监听
  9. 《SAFe 4.0参考指南:精益软件与系统工程的规模化敏捷框架》一 3.13 故事
  10. type traits