vc++调用webservice

正在看着AV(AreCont)SDK的时候,老大突然让我转到soap上,原因是刚进公司的我,第一项任务便是研究ONVIF(so many specifications),当然主要的还是看core specification,这是一个axisbosch and sony 三大牛x整出来的标准规范,为开发网络视频设备软件开发商提供一个标准规范,但是至今为止仍只是少数公司加入了标准规范的行列,可能是他们不求上进吧

         core specification中最主要的还是提到了webservice,兼容RTSPRTCP, RTP 实现实时流传输,采用vc++实现,所以公司还是考虑通过vc++调用webservice,所以老大便给了我这个任务,先熟悉一下。整了一天,才搞了个差不多,感觉很是纳闷,其实程序看起来很简单,但是细节往往能让人迷糊一大段时间。

         其实看了阿瑞得文章后,基本上差不多,当然先装soap toolkit3.0是前提,不过中间还是遇到很多问题的,又通过不断的查阅才得以解决,其中总是发生中断的情况,这个主要是因为webserviceURL没有写正确或者没有搞清URLNamespace Uri的原因吧。不多说了,还是先看我做的流程吧。

First step: New a Asp.net Web Service Application project.

The following is the  content of  Service1.asmx.cs:

using System;

using System.Linq;

using System.Web;

using System.Web.Services;

using System.Web.Services.Protocols;

using System.Xml.Linq;

namespace TestWebService

{

    [SoapDocumentService(RoutingStyle = SoapServiceRoutingStyle.RequestElement)]

    [WebService(Namespace = "http://localhost/WebService/")]

    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

    // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。

    // [System.Web.Script.Services.ScriptService]

    public class Service : System.Web.Services.WebService

    {

        public Service()

        {

            //CODEGEN: 该调用是 ASP.NET Web 服务设计器所必需的

            InitializeComponent();

        }

 

        #region 组件设计器生成的代码

 

        //Web 服务设计器所必需的

        private System.ComponentModel.IContainer components = null;

 

        /**/

        ///

        /// 设计器支持所需的方法 - 不要使用代码编辑器修改

        /// 此方法的内容。

        ///

        private void InitializeComponent()

        {

        }

 

        /**/

        ///

        /// 清理所有正在使用的资源。

        ///

        protected override void Dispose(bool disposing)

        {

            if (disposing && components != null)

            {

                components.Dispose();

            }

            base.Dispose(disposing);

        }

 

        #endregion

 

        // WEB 服务示例

        // HelloWorld() 示例服务返回字符串 Hello World

        // 若要生成,请取消注释下列行,然后保存并生成项目

        // 若要测试此 Web 服务,请按 F5

 

        [WebMethod]

        public int Hello(int strName, int strPwd)

        {

            int temp = strName * strPwd;

            return temp;

        }

 

        [WebMethod]

        public string HelloWorld(int strName, int strPwd)

        {

            return "我是shawn";

        }

        [WebMethod]

        public string GetStringName()

        {

            return "shawn,rock!!!";

        }

    }

}

Then F5 debug mode test the application.

Second step:

New a win32 console application:

New a WSWrapper class:

WSWrapper.h

#ifndef _WS_WRAPPER_H_

#define _WS_WRAPPER_H_

#import "msxml4.dll"

#import "C:/Program Files/Common Files/MSSoap/Binaries/mssoap30.dll" /

    exclude("IStream", "IErrorInfo", "ISequentialStream", "_LARGE_INTEGER", /

    "_ULARGE_INTEGER", "tagSTATSTG", "_FILETIME")

#include

#include

using namespace MSXML2;

using namespace MSSOAPLib30; 

using std::string;

typedef struct

{

    char * sParamName;

    char * sParamValue;

}WSPARAM;

class WSWrapper

{

public:   

    WSWrapper();

    virtual ~WSWrapper();   

    bool InvokeSoap(string wsURL,

                  string wsNameSpace,

                  string wsMethod,

                  WSPARAM  *wsParam,

                  int wsCount,

                  char *sEmsg,

                  char *sRmsg,

                  bool wsXML);

private:

/*  const char *_wsURL;

    const char * _wsNameSapce;

    const char *_wsMethodName;  */

};

 

#endif

WSWrapper.cpp

#include"WSWrapper.h"

#include

#include

using namespace std;

WSWrapper::WSWrapper()

{

 

}

 

WSWrapper::~WSWrapper()

 

{

    try

    {

       CoUninitialize();

    }

    catch(...)

    {

    }  

 

}

 

//   参数说明:

//   wsURL:WEBSERVICE的链接地址

//   wsNameSpace:在页面中定义的命名空间,一般地使用:http://tempuri.org/

//   wsMethod:要访问的WEBSERVICE 方法名

//   wsParam: 要使用的参数,见WSPARAM定义,

//   wsCount: 参数总数

//   sEmsg://要返回给调用函数的错误码率信息

//   sRmsg: //要返回的捃执行结果信息

//   wsXML:要返回的是XML值还是TEXT

//   返回值:

//   如果正常执行返回true,中间有问题就返回false;

 

bool WSWrapper::InvokeSoap(string wsURL,

                        string wsNameSpace,

                        string wsMethod,

                        WSPARAM  *wsParam,

                        int wsCount,

                        char *sEmsg,

                        char *sRmsg,

                        bool wsXML)

{   

 

       HRESULT hr = CoInitialize(NULL);//初始化com环境

       if(FAILED(hr))

       {

           strcpy(sEmsg,"初始化COM失败");

           printf("initialized com failed.");

           return false;

       }

 

       ISoapSerializerPtr Serializer;

       ISoapReaderPtr Reader;

       ISoapConnectorPtr Connector;

 

       //连接到WebService

       hr = Connector.CreateInstance(__uuidof(HttpConnector30));

       if(FAILED(hr))

       {

           //创建com对象出错,一般是因为没有安装com

           strcpy(sEmsg,"创建HttpConnector FAILED");

           printf("create HttpConnector failed.");

           return false;

       }

 

       Connector->Property["EndPointURL"] = wsURL.c_str();

       hr = Connector->Connect();

       if (FAILED(hr))

       {

           strcpy(sEmsg,"连接WEBSERVICE FAILED");

           printf("connecting webservice failed.");

           return false;

       }

       Connector->Property["SoapAction"] = (wsNameSpace + wsMethod).c_str();     

       //开始创建webservice的请求Soap

       Connector->BeginMessage();

       hr = Serializer.CreateInstance(__uuidof(SoapSerializer30));

       if (FAILED(hr))

       {

           strcpy(sEmsg,"CreateInstance Serializer FAILED");

           printf("create instance Serializer failed.");

           return false;

       }

 

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

       Serializer->StartEnvelope("SOAP", "http://schemas.xmlsoap.org/soap/envelope/", "");

       Serializer->SoapAttribute("xsi", "", "http://www.w3.org/2001/XMLSchema-instance", "xmlns");

       Serializer->SoapAttribute("xsd", "", "http://www.w3.org/2001/XMLSchema", "xmlns");

       //Serializer->StartEnvelope("","","");

 

       Serializer->StartBody(L"NONE");

       Serializer->StartElement(wsMethod.c_str(), wsNameSpace.c_str(), "NONE", "");

 

       for (int i = 0; i < wsCount; i++)

       {

           Serializer->StartElement(wsParam[i].sParamName,wsNameSpace.c_str(),"NONE","");

           Serializer->WriteString(wsParam[i].sParamValue);

           Serializer->EndElement();

       }

 

       Serializer->EndElement();

       Serializer->EndBody();

       Serializer->EndEnvelope();       

       try

       {

           Connector->EndMessage();

       }

       catch (...)

       {

           strcpy(sEmsg,"提交SOAP消息出错");

           printf("提交SOAP消息出错");

           return false;

       }

      

       //解析返回的soap

       hr = Reader.CreateInstance(__uuidof(SoapReader30));

       if(FAILED(hr))

       {

           strcpy(sEmsg,"CreateInstance READER FAILED");

           printf("create instance reader failed.");

           return false;

       }

 

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

       if (wsXML)

       {

           strcpy(sRmsg,(const char*)Reader->RpcResult->xml);

       }

       else

           strcpy(sRmsg,(const char*)Reader->RpcResult->text);

       return true;

}

 

The last file is TestApp.cpp:

 

#include "WSWrapper.h"

int main()

{

 

    string url = "http://localhost:1451/Service1.asmx";

    string uri = "http://localhost/WebService/";

    string methodName = "HelloWorld";

 

    WSPARAM *params = new WSPARAM[2];

    params[0].sParamName = "strName";

    params[0].sParamValue = "3";

    params[1].sParamName = "strPwd";

    params[1].sParamValue = "4";

    char errorMessage[20];

    char revMessage[100];

    WSWrapper wsWrapper;

    int wsParaCount = 2;

    bool retValue = wsWrapper.InvokeSoap(url,uri,methodName,params,wsParaCount,errorMessage,revMessage,false);

 

    if (retValue)

    {

       printf("%s",revMessage);

    }

    getchar();

    getchar();

    return 0;

}

 

其实我遇到的一个最大的问题就是没有返回值的问题,最终还是不小心找到了解决方案,就是

Serializer->StartElement("strName", _wsNameSapce.c_str(), "NONE", "");

       //Serializer->SoapAttribute("xsi:type", "", "xsd:string", "");

       Serializer->WriteString("3");       

       Serializer->EndElement();

      

       Serializer->StartElement("strPwd",_wsNameSapce.c_str(),"NONE","");

       Serializer->WriteString("4");

       Serializer->EndElement();

一开始的时候,并没有指定strNamestrPwdnamespace,最好是跟methodnamespace是一致的,就是_wsNameSapce.c_str()。还有一个就是注意当运行webservice的时候把TestApp.cpp中的url改成运行测试webserviceurl路径。当然还遇到了其他很多方面的问题,欢迎有需要的人跟我交流。

 

你可能感兴趣的:(C/C++,webservice,vc++,soap,string,components,asp.net)