用gSOAP开发Web Service程序
2009-07-23 20:25:56
作者:毛毛 来源:www.cppprog.com 浏览次数:14604
网友评论 15
条
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生成的头文件里的变量、类型等名称的前面都会加上名空间前缀,以两个下划线分隔。如上面的命令生成的头文件,有这样的定 义:
-
class
ay1__ArrayOfString;
-
enum
ay1__theDayFlagEnum
-
{
-
ay1__theDayFlagEnum__Today,
-
ay1__theDayFlagEnum__Tomorrow,
-
ay1__theDayFlagEnum__theDayafterTomorrow,
-
};
前面的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方式传送以防止乱码。
-
#include<iostream>
-
#include<string>
-
#include"soapServiceSoapProxy.h"
-
#include& nbsp;"ServiceSoap.nsmap"//表忘了名空间定义
-
-
using
namespace
std;
-
-
-
stringEncodeUtf8(wstringin)
-
{
-
strings(in.length()*3+1,''
);
-
size_t
len=::WideCharToMultiByte(CP_UTF8,0,
-
in.c_str(),in.length(),
-
&s[0],s.length(),
-
NULL,NULL);
-
s.resize(len);
-
return
s;
-
}
-
-
-
wstringDecodeUtf8(stringin)
-
{
-
wstrings(in.length(),_T(''
));
-
size_t
len=::MultiByteToWideChar(CP_UTF8,0,
-
in.c_str(),in.length(),
-
&s[0],s.length());
-
s.resize(len);
-
return
s;
-
}
-
-
int
main(
int
argc,
char
*argv[])
-
{
-
ServiceSoapProxygs(SOAP_C_UTFSTRING);
-
-
_ns1__getWeatherbyCityNamecityname;
-
_ns1__getWeatherbyCityNameResponseresp;
-
-
stringstrCityName=EncodeUtf8(L"苏州"
);
-
cityname.theCityName=&strCityName;
-
cityname.theDayFlag=ns1__theDayFlagEnum__Tomorrow;
-
-
if
(gs.getWeatherbyCityName(&cityname,&resp)==SOAP_OK)
-
{
-
ns1__ArrayOfString*aos=resp.getWeatherbyCityNameResult;
-
wcout.imbue(std::locale("chs"
));
-
for
(vector<string>::iterator
-
itr=aos->string.begin(),itr_end=aos->string.end();
-
itr!=itr_end;++itr)
-
wcout<<DecodeUtf8(*itr)<<endl;
-
-
}
-
-
return
0;
-
}
上面的代码花了一半在UTF8编码转换上,如果参数里没有中文的话,代码会简化很多:
-
ServiceSoapProxygs;
-
_ns1__getWeatherbyCityNamecityname;
-
_ns1__getWeatherbyCityNameResponseresp;
-
stringstrCityName("苏州"
);
-
cityname.theCityName=&strCityName;
-
cityname.theDayFlag=ns1__theDayFlagEnum__Tomorrow;
-
-
if
(gs.getWeatherbyCityName(&cityname,&resp)==SOAP_OK)
-
{
-
ns1__ArrayOfString*aos=resp.getWeatherbyCityNameResult;
-
for
(vector<string>::iterator
-
itr=aos->string.begin(),itr_end=aos->string.end();
-
itr!=itr_end;++itr)
-
cout<<*itr<<endl;
-
}
但是这个代码应用到中文字符串时,会发现返回的是一堆乱码,gSOAP有两种方式支持它:
- 使用宽字符集,如用前文演示的type map文件来转换字符串为std::wstring。
- 使用UTF8传送字符串,这个例子就是使用的这个方式:首先,定义ServiceSoapProxy gs的传送模式为SOAP_C_UTFSTRING;然后输入时把字符串转换成UTF8,得到输出时把UTF8转换回来。
使用UTF8时还要注意一点,如果使用纯C调用,那么应该这样设置UTF8调用:
-
soapsp;
-
soap_init(&sp);
-
soap_set_mode(&sp,SOAP_C_UTFSTRING);
-
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
命令选项注释
:
4.新建项目
把gsoap库里的stdsoap2.cpp文件,以及上一步生成的soapServiceSoapService.cpp和soapC.cpp都加入到 项目。
设置加入的这三个文件为不使用预编译头。
5.编写代码
打开soapcpp2生成的soapServiceSoapService.h文件,在ServiceSoapService类定义里 会看到这样几行字:
它后面的几个方法是要我们自己实现它的,先看代码吧:
-
#include"soapServiceSoapService.h"
-
#include"ServiceSoap.nsmap"
-
-
-
int
ServiceSoapService::getWeatherbyCityName(
-
_ns1__getWeatherbyCityName*ns1__getWeatherbyCityName,
-
_ns1__getWeatherbyCityNameResponse*ns1__getWeatherbyCityNameResponse)
-
{
-
if
(*(ns1__getWeatherbyCityName->theCityName)!=L
"苏州"
)
return
SOAP_USER_ERROR;
-
-
ns1__ArrayOfString*aos=soap_new_ns1__ArrayOfString(this
,-1);
-
-
aos->string.push_back(std::wstring());
-
if
(ns1__getWeatherbyCityName->theDayFlag!=Tomorrow)
-
{
-
aos->string.push_back(L"我只知道明天天气,其它的不要问我!"
);
-
}
-
else
-
{
-
aos->string.push_back(L"有日食,不过下大雨,哈哈,气死你!"
);
-
aos->string.push_back(L"下雨当然有风啦,多大我也不知道"
);
-
}
-
ns1__getWeatherbyCityNameResponse->getWeatherbyCityNameResult=aos;
-
return
SOAP_OK;
-
}
-
-
-
int
ServiceSoapService::getSupportProvince(
-
_ns1__getSupportProvince*ns1__getSupportProvince,
-
_ns1__getSupportProvinceResponse*ns1__getSupportProvinceResponse)
-
{
-
return
SOAP_OK;
-
}
-
-
-
int
ServiceSoapService::getSupportCity(
-
_ns1__getSupportCity*ns1__getSupportCity,
-
_ns1__getSupportCityResponse*ns1__getSupportCityResponse)
-
{
-
return
SOAP_OK;
-
}
-
-
-
int
main(
int
argc,
char
*argv[])
-
{
-
ServiceSoapServicesev;
-
return
sev.run(8888);
-
}
编译,运行,现在我们的本机8888端口开始提供天气预报的SOAP服务了。
修改之前的客户端,在main()里第一行
-
ServiceSoapProxygs(SOAP_C_UTFSTRING);
后面加上:
-
gs.soap_endpoint=
"http://localhost:8888"
;
运行这客户端后可以就看到我们提供的优质服务了:)
本例中getWeatherbyCityName
方 法里的ns1__getWeatherbyCityNameResponse
参 数用于返回数据,它的getWeatherbyCityNameResult
成 员是由我们来申请内存的,这个内存应该用“soap_new_ 类名
”来取得,这些申请函数可以从soapH.h
里找到,如本例的soap_new_ns1__ArrayOfString
。
- 第一个参数是soap类型,它是ServiceSoapService的父类型,也是gSOAP中最重要的类型。
- 第二个指定申请的个数,指定为-1表示只生成一个,否则生成一个指定数目的数组。
分享到:
相关推荐
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
使用opencv决策树训练mushroom数据集-python源码.zip
基于Faster RCNN的人脸检测识别系统python源码+项目说明+wider_face数据集.zip ### 三,使用说明 1. 锚框的大小为[128、256、512],比率为[1:1、1:2、2:1]。 2. tensorflow的版本是'1.9.0',keras的版本是'2.1.5',除了使用tensorflow2.0之后版本,其他版本都可以尝试。不支持python2.x。 3. 使用的是tensorflow backend,theano可以自行修改。 4. wider face的Label文件格式与VOC2012的label不同,而我使用的Faster RCNN需要VOC2012的格式,所以需要将label文件转换一下格式。具体可以查看 [https://blog.csdn.net/qq_37431083/article/details/102742322](https://blog.csdn.net/qq_37431083/article/details/102742322) 5. 在训练过程中可能会出现`"ValueError: 'a' cannot be empty
1985-2022年广东省企业专利明细数据-专利名称专利类型专利摘要专利授权专利 分类号等 1、数据说明: 在知识经济时代,技术创新是实现经济内生增长的关键动力, 科技优势成为经济竞争优势的根本源泉。新一轮科技革命和产业变革加速,全球创新速度加 快,我国正在经历发展方式转变、经济结构优化、新旧动能转换的攻关期,创新日益成为破 解发展难题的关键。专利作为技术与知识的载体,其申请数量是创新研究中衡量创新最常用 的指标之一,中国成为创新领先国家也同样体现在专利申请量上。改革开放 40 年来, 我们的知识产权事业取得了举世瞩目的巨大成功,但也面临着“大而不强”的问题。引导专 利从追求数量向提高质量转变,这是国家近几年的政策扶持重点,也是未来专利申请审查的 一个风向标,针对海量专利数据的价值识别与预测,逐渐成为当前的研究热点。 本数据提 供了1985-2022年广东省的企业专利明细数据,可用于各类专利相关研究。 2、 数据来源: 数据来源为国家知识产权局,利用知识产权局的高级检索,选择地区、年份、 专利类型,对全国31省的各类专利进行统计并将检索结果整理为面板数据,包括发明公开 、发明授权、实用
Kaggle竞赛 稻田病害分类-python源码.zip
文件目录解释 # 1. Models 用来存放的模型,可以是已有的Paddle格式的模型 # 2. Pages - assets 用到的图片资源 - assets.qrc 使用PySide生成的样式文件 - assets_rc.py GUI界面的样式文件,此目录和根目录都有,我忘记是调用的哪一个了,所以都保留了。 # 3. Utils - AttResNet.py 网络代码 - DatasetProcess.py 数据集处理代码 - FaceDetection.py 人脸检测代码 - Predict.py 模型预测代码 - VisualTrain.py 模型训练代码 - CSV文件 用来保存数据集和创建的信息 # 4. Dataset 存放数据集的目录 注意事项 * # 配置好环境,安装使用PySide的工具,不会安装见如下以PyCharm为例的说明 1. 依次点击 File:arrow_right:Settings:arrow_right:Tools:arrow_right:External Tools:arrow_right::heavy_plus_sign:添加PySide工具,
机械设计小线圈生产打蜡机sw20非常好的设计图纸100%好用.zip
触屏版自适应手机wap软件网站模板 触屏版自适应手机wap软件网站模板
基于普中51开发板的超声波测距+蜂鸣器报警 (附开发板原理图) 基于普中51开发板的超声波测距+蜂鸣器报警 (附开发板原理图)
机械设计大倾角输送机sw17非常好的设计图纸100%好用.zip
每个压缩包都附有数据表和数据来源 信心指数 1.投资者信心指数表 数据区间:20 08.04-2022.09,月度数据(数据库中该项数据的全部内容) 字段设置:全 选 全部字段: DeclareDate [发布日期] - YYYY-MM-DD SgnMonth [统计月度] - YYYY-MM IndexCode [指数编 码] - Q4001信心指数;Q4002国内经济基本面;Q4003国内经济政策; Q4004国际经济金融环境;Q4005股票估值;Q4006大盘乐观;Q4007大 盘反弹;Q4008大盘抗跌;Q4009买入; Name [指数名称] - 信心指 数;国内经济基本面;国内经济政策;国际经济金融环境;股票估值;大盘乐观;大盘反弹 ;大盘抗跌;买入; Value [当月值] - LastValue [上月值] - Mom [环比增减] - 压缩包所含文件: 数据样例: 2.消费者信心指数表 数据区间:1999.01-2022.09,月度数据(数据库中该项数据的全部内容 ) 字段设置:全选 全部字段: SgnMonth [统计月度] - YYYY-M M Expect
使用Keras+TensorFlow进行目标检测-python源码.zip
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
触屏版自适应手机wap软件网站模板 触屏版自适应手机wap软件网站模板
触屏版自适应手机wap软件网站模板 触屏版自适应手机wap软件网站模板
触屏版自适应手机wap软件网站模板 触屏版自适应手机wap软件网站模板
lda代码-checkpoint-checkpoint.ipynb
变量如下: Ctnb[城市编号]-城市编号 Prvn[所属省份]-城市所属的省份 Pftn[所属地级市]-城市所属的地级市 Ctn[城市名称]-城市名称 Dat e[日期]-天气数据发布的时间 Dywek[星期时间]-星期时间 Htmpt[最 高气温]-当天天气最高气温,单位:℃ Ltmpt[最低气温]-当天天气最低气温, 单位:℃ Wthcdt[天气情况]-当天天气的具体状况 Wnddrt[风向]-当 天天气风吹来的方向 Wndfrc[风力]-当天天气风力级别 数据展示:
触屏版自适应手机wap软件网站模板 触屏版自适应手机wap软件网站模板
低碳试点城市名单以及程序处理 将选为“低碳城市”试点城市的虚拟变量作为核心解释变 量,当一个城市被批复成为“低碳城市”试点城市当年及以后,该变量取值为1,未入选则 为0