1. 程式人生 > >VC++ 使用soapsdk和gsoap兩種方法呼叫webservice

VC++ 使用soapsdk和gsoap兩種方法呼叫webservice

VC++呼叫webservice

有個專案用到了webserivce,在這裡做個記錄。

2種方法實現VC++呼叫webservice。

第一種方法,使用微軟的soapsdk:

這裡我們直接呼叫網路上免費的webserivce服務來做為用例:http://webservice.webxml.com.cn/webservices/DomesticAirline.asmx

1、需要安裝微軟的soapsdk3開發包,可以從微軟網站下載。

2、首先在工程的BOOL CWHRepeaterApp::InitInstance()裡新增::CoInitialize(NULL);

intCWHRepeaterApp::ExitInstance()裡新增::CoUninitialize();用來初始化COM環境。

2、程式碼如下

#pragma once

#ifndef __CWSWrapper_H__

#define __CWSWrapper_H__

classCWSWrapper

{

public:

         CWSWrapper(const char *szURL,const char *szNameSpace,const char*szMethodName);

         virtual ~CRocWSWrapper(void);

         CStringReceiveXMLData(CString strStartCity,CString strLastCity,CString strDate,CStringstrUserID);

private:

         CStringm_strURL;

         CStringm_strNameSpace;

         CStringm_strMethodName;

};

#endif

#include "StdAfx.h"

#include "RocWSWrapper.h"

#import "msxml4.dll"

#import "C:\Program Files(x86)\Common Files\MSSoap\Binaries\mssoap30.dll" \

         exclude("IStream", "IErrorInfo","ISequentialStream"

, "_LARGE_INTEGER", \

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

#include <Windows.h>

using namespace MSXML2;

using namespace MSSOAPLib30;

usingstd::string;

CWSWrapper::CRocWSWrapper(constchar *szURL,constchar *szNameSpace,constchar *szMethodName)

         :m_strURL(szURL),m_strNameSpace(szNameSpace),m_strMethodName(szMethodName)

{

}

CString CWSWrapper::ReceiveXMLData(CString strStartCity,CStringstrLastCity,CString strDate,CString strUserID)

{

         HRESULT hr;

         ISoapSerializerPtrSerializer;

         ISoapReaderPtrReader;

         ISoapConnectorPtrConnector;

         try

         {

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

                   if (FAILED(hr))

                   {

                            return CString("Error:1");

                   }

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

                   if (FAILED(hr))

                   {

                            return CString("Error:2");

                   }

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

                   if (FAILED(hr))

                   {

                            return CString("Error:3");

                   }

                   Connector->Property["EndPointURL"] = (_bstr_t)m_strURL;

                   //Connector->Property["EndPointURL"] ="http://webservice.webxml.com.cn/webservices/DomesticAirline.asmx";

                   Connector->Connect();

                   Connector->Property["SoapAction"] =_bstr_t(m_strNameSpace+m_strMethodName);

                   //Connector->Property["SoapAction"] ="http://WebXml.com.cn/getDomesticAirlinesTime";

                   //建立webservice的請求soap

                   Connector->BeginMessage();

                   // serializer連線到connector的輸入字串

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

                   // 建立soap訊息

                   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->StartBody("");

                   Serializer->StartElement((_bstr_t)m_strMethodName,(_bstr_t)m_strNameSpace, "", "Soap");         //第三個引數不能填寫NONE

                   //下面傳入四個引數,StartElementEndElement成對出現,用WriteString傳入引數

                   Serializer->StartElement("startCity", "","", "Soap");

                   Serializer->WriteString((_bstr_t)strStartCity);

                   Serializer->EndElement();

                   //

                   Serializer->StartElement("lastCity", "","", "Soap");

                   Serializer->WriteString((_bstr_t)strLastCity); 

                   Serializer->EndElement();

                   //

                   Serializer->StartElement("theDate", "","", "Soap");

                   Serializer->WriteString((_bstr_t)strDate); 

                   Serializer->EndElement();

                   //

                   Serializer->StartElement("userID", "","", "Soap");

                   Serializer->WriteString((_bstr_t)strUserID); 

                   Serializer->EndElement();

                   //

                   Serializer->EndElement();

                   Serializer->EndBody();

                   Serializer->EndEnvelope();

                   _variant_tvar = _variant_t((IUnknown*)Connector->InputStream);

                   Connector->EndMessage();

                   //解析返回的soap

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

                   CStringstrOutput= CString((const char*)Reader->RpcResult->text);

                   return strOutput;

         }

         catch(_com_error &e)

         {

                   ATLTRACE(("error info: %s; \n"), e.ErrorMessage());

         }

         catch(...)

         {

         }

         return CString("Error");

}

呼叫方法:

CRocWSWrapper wrapper("http://webservice.webxml.com.cn/webservices/DomesticAirline.asmx","http://WebXml.com.cn/","getDomesticAirlinesTime");

CString strName = wrapper.ReceiveXMLData(CString("天津"), CString("北京"), CString("2015-1-1"),CString(""));

第二種方法,使用gsoap:

這裡我們直接呼叫網路上免費的webserivce服務來做為用例:http://fy.webxml.com.cn/webservices/EnglishChinese.asmx?op=TranslatorString

http://fy.webxml.com.cn/webservices/EnglishChinese.asmx?wsdl

在頁面裡可以看到服務的SOAP 請求和響應示例。(這對於第一種實現方法很直觀)

1、首先下載gsoap,下載後直接解壓縮即可。這裡我們放到C盤下。

2、在VC工程下建立一個目錄EnglishChinese,把C:\gsoap-2.8\gsoap\bin\win32目錄下的wsdl2h.exe和soapcpp2.exe檔案拷貝到EnglishChinese目錄下,把C:\gsoap-2.8\gsoap目錄下的stdsoap2.cpp和stdsoap2.h檔案也拷貝到EnglishChinese目錄下。此步驟可以省略。

3、在目錄下建立一個批處理檔案。wsdl2h和soapcpp2如何使用可以檢視網路。

@echo off

wsdl2h.exe -s -otestEnCn.h http://fy.webxml.com.cn/webservices/EnglishChinese.asmx?wsdl

soapcpp2.exe -C-IC:\gsoap-2.8\gsoap\import testEnCn.h

pause

如果第二步不拷貝檔案也可以直接在gsoap目錄下進行操作。CMD命令列下執行同樣可以。

4、呼叫批處理或在CMD下執行wsdl2h.exe和soapcpp2.exe。在EnglishChinese目錄下生成了一些檔案。把生成的檔案新增到工程裡,包括soapStub.h,soapH.h,soapC.cpp和soapClient.cpp,另外把stdsoap2.cpp和stdsoap2.h檔案也新增到工程裡。soapClientLib.cpp檔案不需要新增。此時在工程的類視圖裡可以看到很多以ns1__為字首的類或介面函式等。

注意:這些新增的cpp檔案由於是其它軟體生成的,可能會提示錯誤資訊:fatal errorC1010: 在查詢預編譯頭時遇到意外的檔案結尾。是否忘記了向源中新增“#include "stdafx.h

修改對應檔案的“屬性”下“C/C++”下“預編譯頭”下“建立/使用預編譯頭”為“不使用預編譯頭”即可。

5、新增程式碼,在工程的全域性函式和變數中可以看到gsoap生成的函式介面。

#include "StdAfx.h"

#include "EnCn.h"

#include "EnglishChinese\soapH.h"

#include "EnglishChinese\EnglishChineseSoap.nsmap"

voidCEnCn::Test()

{

         //

         struct soap soap;

         struct _ns1__TranslatorString ns1__TranslatorString;

         struct _ns1__TranslatorStringResponse_ns1__TranslatorStringResponse;

         soap_init(&soap);

         soap_set_mode(&soap,SOAP_C_UTFSTRING); 

         ns1__TranslatorString.wordKey= "love";

         soap_call___ns1__TranslatorString(&soap,"http://fy.webxml.com.cn/webservices/EnglishChinese.asmx","TranslatorString",&ns1__TranslatorString,_ns1__TranslatorStringResponse);

         if (soap.error)

         {

                   ;

         }

         else

         {

                   ns1__ArrayOfString*arrStr = _ns1__TranslatorStringResponse.TranslatorStringResult;

                   int iSize = arrStr->__sizestring;

                   char **string = arrStr->string;            

         }

         soap_destroy(&soap);

         soap_end(&soap);

         soap_done(&soap);

}