使用C++实现SOAP客户端与服务端通信

SOAP(Simple Object Access Protocol)是一种协议,用于在网络中交换结构化信息。它被广泛应用于各种Web服务中。本文将介绍如何使用C++实现SOAP客户端服务端的通信。

SOAP工具包

SOAP工具包为开发者提供了学习SOAP的良好起点。微软提供的SOAP工具包2.0 Beta 1版本于2000年1月3日发布,它提供了新的示例和帮助文件来解释新的接口。这些示例包括了客户端和服务端的示例,可以帮助开发者构建自己的服务。

然而,这些示例中有一点被忽视了,那就是使用C++来开发服务。所有的示例都是用VB和ASP编写的,这对于使用SOAP的工作来说并不理想。因此,在网上寻找使用VC的SOAP示例,但只找到了一个,而且它使用的是SOAP工具包1.0而不是最新的2.0版本。

使用C++开发客户端

由于VB示例运行得很好,决定使用VC开发一个客户端应用程序,使其能够与VB Web服务进行通信。从一个低级别的VB计算器程序和从SOAP工具包1.0中得到的VC示例开始。

为了包含SOAPDLL中的COM接口,使用了#import指令。这用于MSSOAP1.dll,并且添加了一个using子句来使用MSSOAPLib命名空间。VB示例使用了WinInetConnector来连接到Web服务器的服务。这个接口不在MSSOAPLib命名空间中。

也导入了WiSC10.dll,以便有了所需的连接器。这次第二次导入导致了问题。在之前的项目中,从未导入过多个DLL。遇到了一个致命的链接错误:fatal error LNK1179: invalid or corrupt file: duplicate comdat "_IID_ISoapConnector"。经过一些研究,发现必须从第二个导入行中移除named_guids。这解决了链接错误,让其余的编码工作变得更加顺利。

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

从这里开始,将VB代码转换为C++接口就变得简单了。这对于以前做过转换的人来说是相当直接的。使用了智能指针来简化对象的创建和释放。

SOAP客户端概述

对于这个VC示例,决定使用在网上找到的一个VC示例作为开发的基础。问题是它是一个控制台应用程序,而不是窗口应用程序。决定仍然使用基于控制台的应用程序开发它,并只使用一种类型的命令向服务器发送。对于大多数VC COM开发者来说,将这段代码包含到一个普通的窗口应用程序中应该是一件小事。

要开始这个低级别的SOAP客户端,需要创建一个SoapConnector。SoapConnector的实现可以使用任何类型的传输协议,如HTTP、FTP或SMTP。SOAP文档说SOAP工具包2.0包含了三种不同的SoapConnector实现。这些实现是WinInetConnector、XmlHttpConnector(9x/Me客户端的默认值)和HttpLibConnector(NT/2K客户端的默认值)。选择使用WinInetConnector,因为代码是基于VB示例的。回去尝试了SoapConnector的其他实现,它们在Win2k上都正确地工作了。

// 创建连接器 Connector = NULL; Connector.CreateInstance(__uuidof(WinInetConnectorLib::WinInetConnector)); // 连接到Web服务 Connector->put_Property(endpoint, vEndPoint); Connector->Connect(NULL); // 开始向服务器发送消息 Connector->put_Property(action, vAction); Connector->BeginMessage(NULL);

创建SoapConnector后,设置了EndPointURL,然后调用了Connect方法。这允许代码连接到Web服务。然后设置SoapAction为uri:Multiply,以告诉服务器将请求的操作。这遵循了工具包中的VB示例。

下一步是创建SoapSerializer。SoapSerializer是允许创建XML消息并将其发送到服务器的接口。

// 创建SoapSerializer Serializer = NULL; Serializer.CreateInstance(__uuidof(SoapSerializer)); // 将序列化器连接到连接器的输入流 Connector->get_InputStream(&inputstream); _variant_t stream = inputstream; Serializer->Init(stream); // 手动构建XML消息 Serializer->startEnvelope(NULL, NULL, NULL); Serializer->startBody(NULL); Serializer->startElement(method, command, NULL, m); Serializer->startElement(a, NULL, NULL, NULL); Serializer->writeString(val1); Serializer->endElement(); Serializer->startElement(b, NULL, NULL, NULL); Serializer->writeString(val2); Serializer->endElement(); Serializer->endElement(); Serializer->endBody(); Serializer->endEnvelope(); // 将消息发送到Web服务 Connector->EndMessage();

创建SoapSerializer后,需要将其附加到SoapConnector的输入流。之后,消息被创建并发送。值得注意的是,当查看源代码时,EndMessage方法是将消息发送到服务器的命令。

到目前为止,已经构建了XML命令并将其发送到服务器执行。下一步是读取结果。在这里省略了错误检查,但可以添加。要读取服务器的回复,客户端应用程序需要使用一个SoapReader。SoapReader连接到SoapConnector的输出流。从那里,可以使用IXMLDOMElement对象读取结果。然后使用std::cout显示。

// 创建SoapReader Reader = NULL; Reader.CreateInstance(__uuidof(SoapReader)); // 将读取器连接到连接器的输出流 Connector->get_OutputStream(&outputstream); _variant_t outstream = outputstream; VARIANT_BOOL bres; Reader->load(outstream, &bres); // 从服务器获取结果并打印 MSSOAPLib::IXMLDOMElement *element; Reader->get_RPCResult(&element); BSTR buff; element->get_baseName(&buff); std::cout << W2A(buff) << std::endl; element->get_text(&buff); std::cout << W2A(buff) << std::endl;

总的来说,SOAP通信对于大多数开发来说都是简单的事情。这里展示的低级通信允许看到XML消息的创建以及解析返回消息。这是一个基于SOAP工具包2.0中的ClcLVBCl示例的简单示例,展示了如何使用VC使用SOAP。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485