易懂易上手WebService客户端——C++之SoapTookit

博客背景介绍:

本是一心想做java工作流,可到公司竟然被指派做C++,C++的任务呢,主要是通信。

这下好了,一个连C++中的HelloWorld都写不出来人,被去写C++程序。呵呵,因为客户的系统是C++版,公司开发工作流是Java版,两者可搭不上话啊,所以哩,C++通信客户端就诞生了。为了协调客户C++与公司Java,C++通信客户端可得发挥其作用了。并且客户C++是C/S结构,而公司Java工作流可是纯纯的B/S结构,所以C++通信客户端这块工作也是需要来协调的。

说到这,想必大家都了解了我目前的工作性质以及C

进入博客主题:

既然被指派,那么只好做下去。不过,工作了十几天,基本上已经适应了。

那就谈谈C++与java通信方式webserice,webserivce不分语言,实际上是一种通信的接口而已。

这篇博客主要讲解一下C++调用WebService,也就是C++作为客户端——soapTookit。

SoapTookit方式比较简单,易懂。并且是自己手写编码,既然是手动编码,则会容易封装。另一种客户端方式gSoap方式,其中个Soap方式使用的命令行工具,命令行工具替我们产生很多头文件,但是个Soap不知如何封装客户端,所以选择了简单易懂的SoapTookit。

使用SoapTookit方式开发WebService客户端,需要安装soapTookit插件。一般安装soapTookit3.0版本。SoapTookit3.0插件会传到网上,方便大家下载。

使用SoapTookit方式开发WebService,编程步骤类似java中的jdbc编程。

首先:创建连接对象。

 
  1. ISoapConnectorPtr connector;   
  2. Connector.CreateInstance(__uuidof(HttpConnector30));  

第二:指定连接服务器的地址。

Connector->Property ["EndPointURL"]=http://localhost:8080/Test/test;

服务器地址,也就是wsdl文件的地址,地址后面可以添加”?wsdl”

如:Connector->Property["EndPointURL"] =http://localhost:8080/Test/test?wsdl;

第三:真正连接服务器。

Connector->Connect();

第四:指定连接服务器上某个动作(方法)。

封装你访问那个方法,比如求和方法,方法名:sum

Connector->Property ["SoapAction"]= "urn:sum";

为了防止写错,也可以写成与第二步一样,直接写wsdl路径。

如:Connector->Property["SoapAction"]= “http://localhost:8080/Test/test”

第五:给第四步中的方法中传递消息(传递参数赋值——输入流)  

 
  1.      // 创建SoapSerializer对象,并用InputSTream进行初始化。  
  2.      ISoapSerializerPtr Serializer;   
  3.      Serializer.CreateInstance(_uuidof(SoapSerializer30));   
  4.      Serializer->Init(_variant_t((IUnknown*)Connector->InputStream));  
  5.   
  6.     //真正发送消息  
  7.     Serializer->startEnvelope("","","");   
  8.  // 开始处理SOAP消息。第一个参数是命名空间,缺省为SOAP-ENV。  
  9.  // 第二个参数定义URI。第三个参数定义Serialzier->startBody("")函数的编码方式。  
  10.  // 开始处理<Body>元素,第一个参数是URI的编码类型,缺省为NONE。  
  11.   Serializer->StartBody("");  
  12. Serializer->StartElement("sum","http://sum","","m");  
  13.   // 开始处理Body里的子元素。  
  14.  // 第一个参数是元素名。第二个参数是URI。  
  15.  // 第三个参数编码类型。第四个参数是元素的命名空间。  
  16. Serializer->StartElement("a","","","");  
  17. Serializer->WriteString("10");  
  18. Serializer->EndElement();  
  19.   
  20. Serializer->StartElement("b","","","");  
  21. Serializer->WriteString("20");  
  22. Serializer->EndElement();  
  23.   
  24.               Serializer->EndElement();  
  25. Serializer->EndBody();  
  26. Serializer->EndEnvelope();  

   仔细观察,可以发现,start与end是匹配的。

第六:读取服务器返回值(输出流方式)

  1. ISoapReaderPtr Reader;  
  2. Reader.CreateInstance(__uuidof(SoapReader30));  
  3. // Connect the reader to the output stream of the connector object.  
  4.  Reader->Load(_variant_t((IUnknown*)Connector->OutputStream), "");  
  5. // Display the result.  www.software8.co
  6.  printf("Answer: %s\n", (const char*)Reader->RpcResult->text);  

开发过程中,需要注意的几个事项:

若返回的结果是:soap server,说明没有匹配上,比如参数名称不对或者输入参数不合格,没有相应的结果。

输入参数中,writeString,只能输出string类型。在c++中输入字符数组或者字符串指针形式。

若是输入参数是int,或long类型,还必须转化成char数组形式或char*形式。

在转化的过程中,注意long或int在内存的长度。

输出结果时,不能只能return (constchar*)Reader->RpcResult->text,因为方法结束后,指针也消亡了,所以会提示错误。需要把结果赋值copy到一个字符串中,然后再返回。

若是返回int或long类型时,则再次由char*转化成int或long类型。

若方法中参数是数组,如何传输呢?

只要把参数名写一样,即可。比如上述sum方法中a是数组参数,则: 

  1.     Serializer->StartElement("a","","","");  
  2. Serializer->WriteString("10");  
  3. Serializer->EndElement();  
  4.   
  5. Serializer->StartElement("a","","","");  
  6. Serializer->WriteString("10");  
  7. Serializer->EndElement();  

     在操作中,需要引入soapTookit3.0中相应的dll表头文件。

    

  1. #import "msxml4.dll"   
  2. using namespace MSXML2;  
  3. //mssoap3.0.dll路径(视情况而定)  
  4. #import"C:/ProgramFiles/CommonFiles/MSSoap/Binaries/mssoap30.dll" /  
  5. exclude("IStream", "IErrorInfo", "ISequentialStream", "_LARGE_INTEGER", /  
  6. "_ULARGE_INTEGER", "tagSTATSTG", "_FILETIME")  
  7. using namespace MSSOAPLib30;  

    所谓的注意事项,是在开发过程中经验吧。SoapTookit插件以及demo源码,我会及时上传的。

后期会继续总结开发webserivce客户端另一种方式gsoap以及开发webserivce服务器端方式gsoap,并且会详细阐述在开发遇到的问题以及解决的方案。

posted @ 2012-09-16 18:30  软件吧  阅读(399)  评论(0)    收藏  举报