vc++调用webservice

来源:互联网 发布:excel数据后的空格删掉 编辑:程序博客网 时间:2024/06/06 09:10

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

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

         其实看了阿瑞得文章后,基本上差不多,当然先装soap toolkit3.0是前提,不过中间还是遇到很多问题的,又通过不断的查阅才得以解决,其中总是发生中断的情况,这个主要是因为webservice得URL没有写正确或者没有搞清URL和Namespace 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;        /**/        /// <summary>        /// 设计器支持所需的方法 - 不要使用代码编辑器修改        /// 此方法的内容。        /// </summary>        private void InitializeComponent()        {        }        /**/        /// <summary>        /// 清理所有正在使用的资源。        /// </summary>        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 <string>#include <Windows.h>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;  */};#endifWSWrapper.cpp#include"WSWrapper.h"#include<cstdlib>#include<cstdio>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();

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



0 0
原创粉丝点击