分享
 
 
 

用Visual C++建立SOAP客户端应用

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

Soap是一个在信息交换中使用得非常广泛的协议,使用方便,并直接可与HTTP, SMTP等其它协议一起工作。本文讨论如何使用Microsoft SOAP Tookit的C++来建立一个简单的SOAP客户端应用。

=========================================================

一、先决条件:

必须熟悉使用COM,特别要熟悉COM中的Smart Pointers。我通过导入方法将COM接口转换成Smart Pointers。系统必须安装了Microsoft SOAP Toolkit和Microsoft XML Parser。文末参考一节介绍如何下载工具箱。文末附件可下载本文源程序。

二、SOAP编程基础:

下面开始介绍一个简单SOAP应用中所包含的类。在此之前,必需先导入所需的类型库,然后程序才能够使用SOAP的类。

导入类型库:

SOAP中使用的对象和接口都在mssoap1.dll文件中。这个文件在安装Microsoft SOAP Toolkit 2.0时生成,存在路径:"C:\Program Files\Common Files\MSSoap\Binaries\MSSOAP1.dll"。用#import将该文件导入到程序中。类型库的内容在导入时被转换成COM smart pointers来描述COM接口。因为SOAP完全依赖于XML,因此必需用Microsoft XML Parser来处理XML。Microsoft XML parser在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客户端应用有以下三步骤:

1- 指定和连接Web服务器。

2- 准备和发送消息。

3- 读取服务端返回的信息。

下面是在基本SOAP客户端要使用到的类:

1- SoapConnector:

在客户/服务模式下,首先要做的事就是连接服务器。SoapConnector类执行客户端与服务端之间的消息传送协议。 SoapConnector是一个抽象类,定义了协议执行的接口。事实上, SoapConnector类不定义执行某种特定的传送协议,例如:MSMQ, MQ Series, SMTP 和 TCP/IP等。 为简便起见,本文只说明使用HTTP传送协议,它是由Microsoft SOAP Toolkit 2.0中的HttpConnector 类来执行的。

SoapConnector类使用步骤如下:

a) 创建SoapConnector类对象:

ISoapConnectorPtr connector;

Connector.CreateInstance(__uuidof(HttpConnector));

b) 指定Web服务器地址:

指定服务器,要做二件事:选择HttpConnector的属性和相应的属性值。本文示例选用EndPointURL属性:

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

以下是属性选项说明(属性名是大小写敏感的):

AuthPassword:客户口令

AuthUser:客户名

EndPointURL :客户URL

ProxyPassword: 代理(proxy)口令

ProxyPort :代理断口

ProxyServer :代理服务器的IP地址或主机名

ProxyUser :代理用户名

SoapAction:HTTP的抬头值。这个属性只使用于低级API。它将忽略SoapClient接口(高级API)中的ConnectorProperty属性 。

SSLClientCertificateName:指定使用Secure Sockets Layer (SSL)加密协议。语法如下:

[CURRENT_USER | LOCAL_MACHINE\[store-name\]]cert-name with the defaults being CURRENT_USER\MY (与Microsoft Internet Explorer用法相同)。

Timeout:HttpConnector的超时限制,以毫秒为单位。

UseProxy:定义是否使用代理(proxy)。缺省值为False。如果将这个属性为真(True),又没有设置上面的ProxyServer值,代理服务器将使用IE里的代理服务器。此时HttpConnector将不理会IE的"Bypass Proxy"(绕道)设置。

UseSSL:定义是否使用SSL(True 或 False)。此值设置为真时,HttpConnector对象不管WSDL设置是HTTP或HTTPS都用SSL连接方式。若此值设置为非真,HttpConnector对象只在WSDL设置为HTTPS时才用SSL方式连接。

c) 与Web服务器连接:

Connector->Connect();

d) 指定动作:

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

e) 启动消息句柄:

必需在SoapSerializer(消息准备函数)之前先启动消息处理机制

Connector->BeginMessage();

在消息处理完毕之后,用EndMessage()函数将消息送往服务器。

.

.

[ 消息准备代码 ]

.

.

Connector->EndMessage();

以上就是与服务器连接的过程。下面介绍如何创建和准备消息。

SoapSerializer:

用于建立送往服务器的SOAP消息。在与服务器通讯之前,SoapSerializer对象必需先与SoapConnector对象连接。SoapSerializer的初始化函数将建立这个内部连接。初始化代入的参数是InputStream (数据流):

// 创建SoapSerializer对象,并用InputSTream进行初始化。

ISoapSerializerPtr Serializer;

Serializer.CreateInstance(_uuidof(SoapSerializer));

Serializer->Init(_variant_t((IUnknown*)Connector->InputStream));

下面是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)里。信封里的<Body>标记中安放信息体,其中包含具体请求。在C++里,用相应的方法来解释这些标记并定义有关的值。

下面的代码说明如何使用这些方法:

Serializer->startEnvelope("SOAP","","");

// 开始处理SOAP消息。第一个参数是命名空间,缺省为SOAP-ENV。

// 第二个参数定义URI。第三个参数定义Serialzier->startBody("")函数的编码方式。

// 开始处理<Body>元素,第一个参数是URI的编码类型,缺省为NONE。

Serializer->startElement("someMethodName","","","m");

// 开始处理Body里的子元素。

// 第一个参数是元素名。第二个参数是URI。

// 第三个参数编码类型。第四个参数是元素的命名空间。

Serializer->WriteString("someParameterValue")

// 写入元素值

在上面的每个startXXX函数后都要又相应的endXXX函数来结尾。消息做完之后,连接器就调用endMessage()方法将消息发送到服务器。

至此,我们已经连接了服务器,制作了相应的消息。最后一个步骤就是接收服务器回应。

SoapReader:

读取服务器返回的信息,将信息解析之后装入DOM,为进一步处理所用。下面是服务器返回的SOAP回应信息:

<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接收服务器返回的信息)。

// 创建SOAPReader对象,并连接到outputstream

ISoapReaderPtr Reader;

Reader.CreateInstance(_uuidof(SoapReader));

Reader->Load(_variant_t((IUnknown*)Connector->OutputStream));

// load方法还可以用于加载XML文件或字符串

将回应信息加载到SoapReader对象之后,就可以用它的RPCResult属性来获取结果。不过,But RPCResult并不直接返回结果,它返回<Body>的第一个实体元素,然后用text属性读取该元素属性值:

Reader->RPCResult->text

三、举例说明一个简单的SOAP客户端应用:

本文示例用www.xmethods.net做服务器。这个服务器指向Yahoo在线信息。

可以在http://www.xmethods.net/ve2/ViewListing.po?serviceid=156找到有关细节。

下面的代码中要输入一个参数,即Yahoo的用户ID。返回结果为0表示离线,1表示在线。

其他细节可参阅:http://www.allesta.net:51110/webservices/wsdl/YahooUserPingService.xml

四、参考:

The SOAP specification Simple Object Access Protocol (SOAP) 1.1 - W3C Note :

http://www.w3.org/TR/SOAP

Microsoft SOAP Toolkit Download :

http://download.microsoft.com/download/xml/soap/2.0/w98nt42kme/EN-US/SoapToolkit20.exe

五:本文示例的SOAP代码:

#include <stdio.h>

#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;

// 连接服务器

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->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();

// 向服务器发送信息

Connector->EndMessage();

// 读取回应

Reader.CreateInstance(__uuidof(SoapReader));

// 连接输出流

Reader->Load(_variant_t((IUnknown*)Connector->OutputStream), "");

// 显示结果

printf("Answer: %s\n", (const char *)Reader->RPCResult->text);

CoUninitialize();

}

本文附件

http://www.topxml.com/snippetcentral/snippetfiles/v20020425121357.zip

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有