C++ 调用 SOAP Web Service
C++ 调用 SOAP Web Service
背景
首先,gSoap 肯定是个不错的选择,但是如果你的程序要调用多个 Web Services(即有多个 WSDL),gSoap 会比较麻烦。还有一个问题就是,gSoap 从 WSDL 自动生成的代码实在是太难用了。当然,这些都不是什么问题,真在的问题是许可证(License),gSoap 用在商业产品中是要收费的。
公司比较穷,舍不得花钱买 gSoap,但是 C++ 调 Web Service 还真没什么好办法。尝试了五六个半死不活的库后,最终锁定了 WWSAPI(Windows Web Services API)。
WWSAPI 的官方文档经常让人摸不着头脑,没有完整的示例,给出一段代码,常常需要几经调整才能使用。WWSAPI 自动生成的代码,是纯 C 的接口,在难用程度上,较 gSoap 有过之而无不及。在消息参数上,它强制使用双字节 Unicode,我们的输入输出都是 UTF8 的 std::string
,于是莫名地多出很多编码转换。WWSAPI 需要你手动分配堆(heap),需要你指定消息的缓冲大小,而最严重的问题是,它不够稳定,特别是在子线程里调用时,莫名其妙连接就会断掉。
于是,我就动手自己写了个 webcc。
一开始 webcc 只支持 SOAP,名字就叫 csoap,后来支持了 REST,于是改名为 webcc,取 Web C++ 的意思。
原理
Webcc 没有提供从 WSDL 自动生成代码的功能,一来是因为这一过程太复杂了,二来是自动生成的代码一般都不好用。所以 webcc 最好搭配 SoapUI 一起使用。SoapUI 可以帮助我们为每一个 Web Service 操作(operation)生成请求的样例,基于请求样例,就很容易发起调用了,也避免了直接阅读 WSDL。
下面以 ParaSoft 提供的 Calculator 为例,首先下载 WSDL,然后在 SoapUI 里创建一个 SOAP 项目,记得勾上 "Create sample requests for all operations?" 这个选项,然后就能看到下面这样的请求样例了:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cal="http://www.parasoft.com/wsdl/calculator/">
<soapenv:Header/>
<soapenv:Body><cal:add><cal:x>1</cal:x><cal:y>2</cal:y></cal:add>
</soapenv:Body>
</soapenv:Envelope>
这个操作是 add
,有两个参数:x
和 y
。此外值得注意的还有 XML namespace,比如 xmlns:cal="http://www.parasoft.com/wsdl/calculator/"
。
要调用这个 add
操作,只要发一个 HTTP 请求,并把上面这个 SOAP Envelope 作为请求的 Content。在 SoapUI 里把 Request 切换到 “Raw" 模式,就可以看到下面这样完整的 HTTP 请求:
POST http://ws1.parasoft.com/glue/calculator HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: "add"
Content-Length: 300
Host: ws1.parasoft.com
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cal="http://www.parasoft.com/wsdl/calculator/"><soapenv:Header/><soapenv:Body><cal:add><cal:x>1</cal:x><cal:y>1</cal:y></cal:add></soapenv:Body>
</soapenv:Envelope>
所以 webcc 所做的,只不过是跟 ws1.parasoft.com
建立 TCP Socket 连接,然后发送上面这段内容而已。
用法
首先,创建一个类 CalcClient
,继承自 webcc::SoapClient
:
#include <string>
#include "webcc/soap_client.h"class CalcClient : public webcc::SoapClient {
public:CalcClient() {Init();}
在 Init()
函数里,初始化 URL、host、port 等等:
private:void Init() {url_ = "/glue/calculator";host_ = "ws1.parasoft.com";port_ = ""; // Default to "80".service_ns_ = { "cal", "http://www.parasoft.com/wsdl/calculator/" };result_name_ = "Result";}
由于四个计算器操作(add, subtract, multiply 和 divide)都一致的具有两个参数,我们可以稍微封装一下,弄一个辅助函数叫 Calc
:
bool Calc(const std::string& operation,const std::string& x_name,const std::string& y_name,double x,double y,double* result) {// Prepare parameters.std::vector<webcc::Parameter> parameters{{ x_name, x },{ y_name, y }};// Make the call.std::string result_str;webcc::Error error = Call(operation, std::move(parameters), &result_str);// Error handling if any.if (error != webcc::kNoError) {std::cerr << "Error: " << error;std::cerr << ", " << webcc::GetErrorMessage(error) << std::endl;return false;}// Convert the result from string to double.try {*result = boost::lexical_cast<double>(result_str);} catch (boost::bad_lexical_cast&) {return false;}return true;
}
值得注意的是,作为局部变量的参数(parameters),利用了 C++11 的 Move 语义,避免了额外的拷贝开销。
当参数为很长的字符串时(比如 XML string),这一点特别有用。
最后,四个操作就是简单的转调 Calc
而已:
bool Add(double x, double y, double* result) {return Calc("add", "x", "y", x, y, result);
}bool Subtract(double x, double y, double* result) {return Calc("subtract", "x", "y", x, y, result);
}bool Multiply(double x, double y, double* result) {return Calc("multiply", "x", "y", x, y, result);
}bool Divide(double x, double y, double* result) {return Calc("divide", "numerator", "denominator", x, y, result);
}
局限
当然,webcc 有很多局限,比如:
- 只支持
int
,double
,bool
和string
这几种参数类型; - 只支持 UTF-8 编码的消息内容;
- 一次调用一个连接;
- 连接是同步(阻塞)模式,可以指定 timeout(缺省为 15s)。
依赖
在实现上,webcc 有下面这些依赖:
- Boost 1.66+;
- XML 解析和构造基于 pugixml;
- 构建系统是 CMake,应该可以很方便地集成到其他 C++ 项目中。
C++ 调用 SOAP Web Service相关推荐
- Java如何通过WSDL文件来调用这些web service
下面我们来看Java如何通过WSDL文件来调用这些web service: 注意,以下的代码并没有经过真正的测试,只是说明这些情况,不同版本的Axis相差很大,大家最好以apache网站上的例子为准, ...
- abap 调用外部web service 使用小结
abap调用外部 web service 时,大致分为以下三个步骤 1,se80,选择package,点击创建enterprise service/web service-proxy client 2 ...
- 使用 Ajax 调用 SOAP Web 服务,第 1 部分: 构建 Web 服务客户机
James Snell (jasnell@us.ibm.com), 软件工程师,新兴技术, IBM James Snell 是 IBM 的 software group 中的 emerging Int ...
- CORBA 简单了解和JAVA与C++互操以及C++调用Java web service
CORBA了解 CORBA(Common Object Request Broker Architecture, 公共对象请求代理体系结构)是由OMG(对象管理组织,Object Management ...
- 调用天气预报Web Service
调用天气Web Service i.创建项目 项目名称:weatherclient ii.创建本地的wsdl文件 ...
- SOAP/Web Service/WSDL关系
转载----------------------------------------------- 最近看了xml schema,xpah,和xslt的相关内容,感觉wsdl就是一个soap的sche ...
- SAP调用外部web service
前提:外部提供可用的web service,通常为链接 1. SE80,创建web service proxy 1)SE80,选择package,右击->create->Enterp ...
- 【REST SOAP】REST和SOAP Web Service的区别比较
今天遇到一个webservice协议的接口需求,在使用soupUI测试接口连通性的时候,发现使用soupUI新建一个SOAP项目的时候,WSDL链接总是报错打不开(厂家提供的接口规范上写的是SOAP协 ...
- Soap Web Service和Rest
Soap: 是一个严格定义的信息交换协议,用于在Web Service中把远程调用和返回封装成机器可读的格式化数据.事实上SOAP数据使用XML数据格式,定义了一整套复杂的标签,以描述调用的远程过程, ...
最新文章
- 基于半监督学习的单体型组装算法
- Oauth2认证以及新浪微博开放平台应用
- Exchange2007中创建收件人对象、通讯组和地址列表和客户端访问
- java知识点--基础篇(5)
- Fallout 3完结
- python判断值是否为空(亲测)
- HDU - 2896 病毒侵袭(AC自动机)
- 异步重试_异步重试模式
- java溢出怎么处理_java数据溢出怎么处理?
- java策略模式学习
- 英特尔生产17个量子位超导芯片,现已交付合作伙伴
- 分表分库解决方案(mycat,tidb,shardingjdbc)
- CloudStack升级中文指南:4.1.x/4.2.x 至4.3版本
- 高等数学18讲(19版)7.29
- Vue3,Vite3,TS,Naive-UI整合TailwindCSS
- python 前缀和总结
- Thinkpad E430 移除网卡白名单
- 笔记本损耗60 计算机提示,笔记本电池损耗60%多怎么处理!
- 5、html标签中的两种关系
- 【悟空云课堂】第三十九期:违反信任边界(CWE-501: Trust Boundary Violation)
热门文章
- php arsort函数,php-常用函数
- IntelliJ IDEA License Activation系列验证爆错: This license BIG3CLIK6F has been cancelled d 解决
- 画布上面重叠事件_python学习手札turtle库的键盘事件
- HTML表单效果图,html-图片/表格/表单
- python opencv识别点个数_python+OpenCV 特征点检测
- 比较有名的CSS,优雅地写css
- kafka jar包_Windows环境下Flink消费Kafka实现热词统计
- 网警已进入本群代码_“闯黄灯”记3分罚200元?沈阳网警这样回应
- vue项目 构建 打包 发布 三部曲
- 计算机组成原理试卷分析,《计算机组成原理与汇编语言》试卷分析报告.doc.docx...