使用VISUAL C++开发SOAP客户端应用

2024-05-10 07:08

本文主要是介绍使用VISUAL C++开发SOAP客户端应用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简介

  在本篇文章中,我们将讨论如何使用Visual C++开发一个简单的SOAP客户端应用程序,我们还将介绍SOAP API的使用。SOAP是互联网上一种非常流行的交换信息用的协议,由于是为了与HTTP、SMTP和其他的类似协议协同工作的,因此它十分简单。用它描述的信息能够被轻易地通过互联网发送到另外的计算机上,而无需担心遭到防火墙等网络安全技术的拦截。

  在这里,我们假设读者已经对SOAP协议有了一定的理解,而且对C++比较精通。如果读者对SOAP还不熟悉,可以查看相关的资料。我们还假设读者熟悉COM的使用,特别是COM中的智能指针,因为在这篇文章中,我们将使用导入命令将COM接口转换为智能指针。另外,读者还需要安装了微软的SOAP工具包。

   SOAP编程基础

  我们将以介绍一个与基本的SOAP应用程序有关的类开始我们的SOAP编程之旅。然而,我们还必须首先导入必需的类型库,我们的应用程序才能使用SOAP类。

   导入类型库

  SOAP中使用的所有对象和接口都包含在mssoap1.dll中,这个文件包含在Microsoft SOAP Toolkit 2.0中。我们可以在C:\Program Files\Common Files\MSSoap\Binaries\MSSOAP1.dll中发现该文件。使用#import命令就可以将该文件导入到我们的源文件中。类库文件中的内容将被转换为描述了COM接口的COM智能指针。

  SOAP使用XML作为其数据格式,因此我们还需要微软的XML Parser来处理XML内容,它包含在msxml3.dll中。在导入mssoap1.dll文件之前,我们还需要导入该文件,如下所示:

#import "msxml3.dll"

using namespace MSXML2;

#import "C:\Program Files\Common Files\MSSoap\Binaries\MSSOAP1.dll" \ 
exclude("IStream", "ISequentialStream", "_LARGE_INTEGER", \ 
"_ULARGE_INTEGER", "tagSTATSTG", "_FILETIME") 
using namespace MSSOAPLib;

  上面是开发一个SOAP应用程序所必需包含的所有类定义。开发一个SOAP客户端应用程序需要三个步骤:

   ·指定并连接一个互联网服务。

   ·准备并发送消息。

   ·读取来自服务器的响应。

  下面是我们用来开发一个基本的SOAP客户端应用程序所需要用到的类:

    SoapConnector 

  在客户机/服务器模式中任何客户端应用程序需要作的第一件事就是与服务器进行连接。SoapConnector就是被用来实现客户机端、服务器端应用程序连接器的协议,它还充当定义实现其他协议接口的抽象类,也就是说,SOAP不仅仅局限于充当一种特定的协议。我们会发现,它的一些实现还支持MSMQ、MQ Series、SMTP和TCP/IPTransports。为了简单起见,我在这里只讨论它作为HTTP Transport的用途,这是由微软SOAP Toolkit 2.0中的HttpConnector类实现的。
使用SoapConnector类所需要的步骤

  首先,创建SoapConnector类的一个对象:

ISoapConnectorPtr connector; Connector.CreateInstance(__uuidof(HttpConnector));

  然后,指定Web服务的地址。接下来,我们必须详细描述该Web服务。Web服务是由Property(HttpConnector的一个属性)指定的。在处理这一属性时有件事情需要指定:我们引用的哪个属性以及该属性的值。下面,我们使用EndPointURL属性指定Web服务:

Connector->Property ["EndPointURL"] = "some url pointing to web service";

  下面的表格提供了一个属性清单(属性的名字是大小写敏感的)

属性 描述
AuthPassword 端点认证用的口令。
AuthUser 端点认证用的用户名。
EndPointURL 端点的URL。
ProxyPassword 代理认证的口令。
ProxyPort 代理服务器使用的端口。
ProxyServer 代理服务器的主机名或IP地址。
ProxyUser 代理认证的用户名。
SoapAction HTTP头部中SoapAction中的值。这一属性只能从低级的API中设定,如果使用SoapClient接口中的ConnectorProperty属性(高级API)设置该属性,它就会被忽略。
SSLClientCertificateName 如果存在,则该字符串标明用于SSL协议中的客户端证书。其语法为: SSLClientCertificateName [CURRENT_USER | LOCAL_MACHINE\[store-name\]]证书名,其缺省的名字为 CURRENT_USER\MY。
Timeout HttpConnector的超时时间,这一时间是以毫秒计算的。
UseProxy 一个类型为布尔型的属性,表明是否使用代理服务器。缺省情况下,这一属性的值被设定为False,表明无需使用代理服务器。如果要使用代服务器,需要将该属性的值设置为True。如果将该属性的值设置为True, 而又没有设置ProxyServer属性,HttpConnector将使用IE中设置的代理服器。HttpConnector会忽略IE中的“不使用代理服务器”设置。
UseSSL 表明是否使用了SSL的布尔型值。如果该属性被设置为True,则无论WSDL中是否指定了HTTP或HTTPS,HttpConnector对象都使用SSL连接。
 如果该属性的值被设置为False,则只有在WSDL中指定了HTTPS的情况下, HttpConnector对象才会使用SSL连接。

  其次,我们需要与Web服务连接。HttpConnector类的Connect方法用来初始化SoapConnector对象和准备与Web服务的连接。

   Connector->Connect();

  在与服务器连接后,我们需要指定Web服务完成的操作。为了指定该操作,我们需要再次使用SoapConnector的Property属性:

Connector->Property ["SoapAction"] = "some uri";

  在完成与Web服务的连接和其他的细节后,我们就可以调用向服务器发送SOAP信息的方法了,必须在调用SoapSerializer的其他方法之前调用该方法:

Connector->BeginMessage();

  在完成与信息相关的操作后,我们必须调用EndMessage()函数,将消息真正地发给Web服务。



[ 消息准备代码 ] 


Connector->EndMessage();

  上面的步骤就是完成与Web服务的实际连接所必需的操作。在下面的部分,我们将讨论如何创建和准备一个信息。
SoapSerializer

  SoapSerializer对象用来构建一个向Web服务发送的SOAP消息。在与服务器连接前,SoapSerializer对象必须与SoapConnector对象连接。为了使这二个对象相互连接,我们需要调用SoapSerializer对象的Init方法,该方法需要一个参数InputStream(向服务器发送数据的流):

// 创建一个SoapSerializer对象,并使用InputSTream对它进行初始化

ISoapSerializerPtr Serializer; Serializer.CreateInstance(_uuidof(SoapSerializer)); Serializer->Init(_variant_t((IUnknown*)Connector->InputStream));

  在讨论SoapSerializer的其他函数以前,我们来看一个SOAP请求的例子:

<SOAP: Envelope xmlns:SOAP="soap namespace"> 
<SOAP:Body> 
<m:someMethodName xmlns:m="some namespace"> 
<someParameter> someParameterValue </someParameter> 
<m:someMethodName> 
</SOAP:Body> 
</SOAP: Envelope>

  SOAP请求被封装在了标记中。<Envelope>标记是该SOAP文档的主标记,SOAP消息通常都被封装在<Envelope>元素中,<Envelope>元素包含一个由<Body>标记指定的消息体,该消息体包含着实际的请求。在C++中,有非常合适的方法可以创建这些标记并指定其值。下面的代码说明了如何利用这些方法:

Serializer->startEnvelope("SOAP","",""); 
// 开始SOAP消息中的一个元素,第一个参数描述了名字空间,

// 如果它是空值,就会缺省地使用SOAP-ENV。第二、第三个参数

// 分别描述了URI和编码类型。
Serialzier->startBody("");

// 消息中<Body>元素的开始,第一个参数描述了编码风格Uri,其缺省的值为NONE。
Serializer->startElement("someMethodName","","","m");

// SOAP消息中<Body>元素的子元素的开始。第一个参数是子元素名字

//第二个参数是URI,第三个参数是编码类型,最后一个参数是元素的名字空间。
Serializer->WriteString("someParameterValue")

// 写元素的值

  上面以startXXX开头的函数都相应地有以endXXX开头、结束元素的函数。在完成消息后,系统会调用连接的endMessage()方法,真正开始向服务发送消息。

  现在我们已经与服务相连接,准备好了我们的请求,并将它发送给了服务。最后一个步骤就是读取来自服务器的响应。下面我们就来讨论这一问题。

  SoapReader 

  该对象读取来自Web服务的响应,并将它解析为DOM,以备进一步处理之用。下面是一个来自Web服务的响应的例子:

<SOAP: Envelope xmlns:SOAP="soap namespace"> 
<SOAP:Body> 
<m:someMethodNameResponse xmlns:m="some namespace"> 
<return> someResult </return> 
<m:someMethodNameResponse> 
</SOAP:Body> 
</SOAP: Envelope>

  在调用任何方法获取结果前,我们联接OutputStream,读取存储在SoapReader对象中的响应(OutputStream用于接收来自Web服务的数据):

// 创建SOAPReader对象和与outputstream联接的代码

ISoapReaderPtr Reader; Reader.CreateInstance(_uuidof(SoapReader)); Reader->Load(_variant_t((IUnknown*)Connector->OutputStream));

// load方法也能够接收XML文档文件或字符串

  在将Web服务的响应加载到SoapReader对象后,我们可以通过调用SoapReader对象的RPCResult属性获得相应的结果,但RPCResult并不返回真正的结果,它返回的是<Body>元素中第一个条目的第一个子元素。我们可以通过调用text属性返回真正的结果:

Reader->RPCResult->text

  一个SOAP客户端应用程序的例子

  为了说明如何使用本篇文章中讨论的SOAP类,我们使用了http://www.xmethods.net/上列出的一项服务,该服务能够显示用户是否正在使用Yahoo Messenger。它只需要一个参数,即Yahoo用户的登录ID。返回的结果是一个布尔型值,0表示用户不在线,1表示用户在线。

  我一直认为,学习某种编程技术的最好的方法就是实地学习源代码,在这里,我们就采取这种方法。下面是使用SOAP调用发现Yahoo用户是否在线的一个控制台应用程序的C++代码:

#include

#import "msxml3.dll" 
using namespace MSXML2;

#import "C:\Program Files\Common Files\MSSoap\Binaries\MSSOAP1.dll" \ 
exclude("IStream", "ISequentialStream", "_LARGE_INTEGER", \ 
"_ULARGE_INTEGER", "tagSTATSTG", "_FILETIME")

using namespace MSSOAPLib;

void main() 

CoInitialize(NULL);

ISoapSerializerPtr Serializer; 
ISoapReaderPtr Reader; 
ISoapConnectorPtr Connector;

// 与Web服务连接
Connector.CreateInstance(__uuidof(HttpConnector)); 
Connector->Property["EndPointURL"] = "http://www.allesta.net:51110/webservices/soapx4/isuseronline.php"; 
Connector->Connect();

// 开始消息
Connector->Property["SoapAction"] = "uri:allesta-YahooUserPing"; 
Connector->BeginMessage();

// 创建SoapSerializer对象
Serializer.CreateInstance(__uuidof(SoapSerializer));

// 将serializer连接到connector的输入字符串
Serializer->Init(_variant_t((IUnknown*)Connector->InputStream));

// 创建SOAP消息
Serializer->startEnvelope("","",""); 
Serializer->startBody(""); 
Serializer->startElement("isuseronline","uri:allesta-YahooUserPing","","m"); 
Serializer->startElement("username","","",""); 
Serializer->writeString("laghari78"); 
Serializer->endElement(); 
Serializer->endElement(); 
Serializer->endBody(); 
Serializer->endEnvelope();

// 将该消息发送给web服务
Connector->EndMessage();

// 读取响应
Reader.CreateInstance(__uuidof(SoapReader));

// 将reader联接到connector的输出字符串
Reader->Load(_variant_t((IUnknown*)Connector->OutputStream), "");

// 显示结果
printf("Answer: %s\n", (const char *)Reader->RPCResult->text); 
CoUninitialize();

}

  我们可以看到,代码十分简单,即使没有使用过C++,我保证读者也能够理解上面代码的作用:首先,它与远程服务器连接;其次,它创建SOAP消息并向web服务发送该消息;最后,读取服务器的响应,并使用printf将它输出到屏幕上。

  结论

  在本篇文章中,我们讨论了如何使用Visual C++建立一个简单的SOAP客户端应用程序。我们还学习了SOAP Toolkit中的几个方法以及如何使用SOAP从服务器获取数据。希望通过本篇文章,使读者能够掌握如何使用C++开发SOAP客户端应用程序。

这篇关于使用VISUAL C++开发SOAP客户端应用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/975780

相关文章

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个