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"
"_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
//下面傳入四個引數,StartElement和EndElement成對出現,用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);
}