在C++中使用soap toolkit访问Web Service(转)

  在C++中使用soap toolkit访问Web Service,一般要用到以下几个接口:
  • ISoapConnector
  • ISoapSerializer
  • ISoapReader
      这三个接口顾名思义。ISoapConnector实现了在对象之间发送和接收SOAP消息的传输协议;ISoapSerializer用于序列化(串行化),创建、封装SOAP消息;ISoapReader用于读取SOAP消息,将SOAP消息解析为一个DOM模型,并提供了一系列操作该DOM模型的方法。
      使用Soap Toolkit的应用程序,需要引入动态库MSSOAP1.dll(当前最新版本是Soap Toolkit3.0:MSSOAP3.dl),同时还需要msxml3.dll用于解析DOM和XML。在程序的开头可以这样来引入相关的文库和名称空间:
      #import "msxml3.dll"
      using namespace MSXML2;
      #import "D:\Program Files\Common Files\MSSoap\Binaries\MSSOAP1.dll" \
      exclude("IStream", "ISequentialStream", "_LARGE_INTEGER", "_ULARGE_INTEGER",
                  "tagSTATSTG", "_FILETIME")
      using namespace MSSOAPLib;
 
      废话少说,觉得还是来分析一段示例代码比较实在。 假设在Web服务器上(如http://localhost/MyTestWebService/),有一个名为Loginout的Web服务,并提供了一个Web Mothod,原型如下:
string LoginTest(string strIP, int nPort);
      下面的代码说明了如何来访问该Web服务。    

 ISoapConnectorPtr Connector; 
 ISoapSerializerPtr Serializer;
 ISoapReaderPtr Reader;
 // 与Web服务连接
 Connector.CreateInstance(__uuidof(HttpConnector));
 Connector->Property[L"EndPointURL"] =
                  _variant_t( "http://localhost/MyTestWebService/Loginout.asmx");
 HRESULT result = Connector->Connect();
 // 创建SoapSerializer对象
 Serializer.CreateInstance(__uuidof(SoapSerializer));
 // 将serializer连接到connector的输入字符串
 Serializer->Init(_variant_t((IUnknown*)Connector->InputStream));

 Connector->Property["SoapAction"] = "http://tempuri.org/LoginTest"
 // 开始soap消息
 Connector>BeginMessage();
 // 创建SOAP消息
 Serializer->startEnvelope("","","");
 Serializer->startBody("");
 Serializer->startElement("LoginTest","http://tempuri.org/","","");
 Serializer->startElement("strIP","http://tempuri.org/","","");
 Serializer->writeString("192.168.1.170");
 Serializer->endElement();
 Serializer->startElement("nPort","http://tempuri.org/","","");
 Serializer->writeString("8000");
 Serializer->endElement(); 
 Serializer->endElement();
 Serializer->endBody();
 Serializer->endEnvelope();
 // 将该soap消息发送给web服务
 Connector->EndMessage();
 // 读取响应soap消息
 Reader.CreateInstance(__uuidof(SoapReader));
 // 将reader联接到connector的输出字符串
 Reader->Load(_variant_t((IUnknown*)Connector->OutputStream), "");
 DWORD dwRt = GetLastError();
 // 显示结果
 printf("Soap return result: %s \n",(const char *)Reader->RPCResult->text);

 CoUninitialize();  

      上面程序将打印出Web服务的返回值。
      几点说明:
  1. http://localhost/MyTestWebService/Loginout.asmx 是提供Web服务的URL。
  2. "http://tempuri.org/"是Web服务所属的名称空间(如果Web服务提供者没有指定名称空间,将会使用该默认名称空间)。
  3. 设置Property时的SoapAction就是要调用的WebMethod“http://tempuri.org/LoginTest"。我觉得称作SoapOperation似乎更好理解些。
  4. Reader->RPCResult->text是调用WebMethod的string类型返回值。如果要读取返回的参数或复杂对象,可以使用ISoapReader的相关方法。
  5. 另外,按上述方法,如果相关参数中含有中文,service服务器接收到的相应内容可能会是乱码!例如我做demo时server端是基于.NET的,字符串肯定是Unicode,以两个字节表示;而soap toolkit默认的xml编码规则是UTF-8(使用该编码,虽然也称为Unicode,但是汉字会被编码为2到3个字节不等),这就产生了冲突。解决的办法是soap调用startEnvelope()时第三个参数指定encoding:UTF-16,这样所有字符均是以2个字节编码。
posted @ 2009-10-25 23:14  装配中的脑袋  阅读(1265)  评论(1编辑  收藏  举报