最近要利用C++調用WebService接口,中間工具是gSoap,IDE:VS2010,WebService接口:http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl
關於Soap,它是一種簡單對象訪問協議,是一種輕量的、簡單的、基於 XML 的協議,它被設計成在 WEB 上交換結構化的和固化的信息。它是一種通信協議,用於Web應用程序之間的因特網通信,它提供一組不受平台和語言限制的方法使應用程序得以相互之間進行Intertnet通信。而gSoap可以看做是對soap的一個實現封裝,它隱藏了在調用WebService中的大量實現細節,使得C++調用WebService變得較為簡單。它提供編譯工具(實際就是針對接口的WSDL生成類文件),然后引入工程操作生成類即可達到訪問WebService接口的目的。仔細查看生成的文件就會發現生成的類與WebService接口的WSDL文件實際相對應的。
WSDL,最初弄的WSDL的時候被這個WSDL弄的焦頭爛額的。這個文件實際上就是WebService的對外接口文件,它是一個XML文件,描述了WebService接口的外部方法和抽象方法,以及各協議下的相關調用,是一個用來描述Web服務和說明如何與Web服務通信的XML語言,為用戶提供詳細的接口說明書。對於WSDL文件,只需要在瀏覽器中打開,即可查看到WebService接口的外部供調用的方法。
對於Soap,gSoap,WSDL就大致介紹到這里,這里記錄如何在C++中調用WebService接口,以http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl為例,一個查詢手機號碼歸屬地的WebService接口。
下載gSoap-2.8版本解壓放置D盤,在命令行下進入gSoap-2.8/gsoap/bin/win32目錄。網絡上有不少gSoap的下載,讀者可自行下載。
然后運行命令:wsdl2h -s -o service1.h http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl,這時在wsdl2h.exe目錄下生成service1.h頭文件,然后運行命令:soapcpp2 -C -x service1.h生成其他的文件,在我的目錄下生成了這些文件:

第一個紅色圈圈里面都是生成的文件,要全部引入工程,其中soapClientLib.cpp文件無用,不引入,引入會報錯。然后將gSoap-2.8/目錄喜愛的stdsoap2.h/cpp也要引入工程。
取消soapC.cpp,soapClient.cpp,stdsoap2.cpp這三個文件的預編譯頭,在stdafx.h文件中增加#include"MobileCodeWSSoap.nsmap"
從webService獲取數據:
- void callService()
- {
- LOG_TRACE_METHOD();
- struct soap soap;
- char* str="";
- wchar_t* str_1 = NULL;
- int b=0;
- class _ns1__getMobileCodeInfoResponse resultStr;
- class _ns1__getMobileCodeInfo a;
- soap_init(&soap);
- soap_set_mode(&soap,SOAP_C_MBSTRING);
- a.mobileCode = ConvAnsiToUtf8("18600960941");
- soap_call___ns2__getMobileCodeInfo(&soap,"http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl","",&a,&resultStr);
- if (soap.error)
- {
- soap_print_fault(&soap, stderr);
- }
- else
- {
- str = resultStr.getMobileCodeInfoResult;
- std::cout << str << endl;
- }
- soap_destroy(&soap);
- soap_end(&soap);
- soap_done(&soap);
- }
void callService()
{
LOG_TRACE_METHOD();
struct soap soap;
char* str="";
wchar_t* str_1 = NULL;
int b=0;
class _ns1__getMobileCodeInfoResponse resultStr;
class _ns1__getMobileCodeInfo a;
soap_init(&soap);
soap_set_mode(&soap,SOAP_C_MBSTRING);
a.mobileCode = ConvAnsiToUtf8("18600960941");
soap_call___ns2__getMobileCodeInfo(&soap,"http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl","",&a,&resultStr);
if (soap.error)
{
soap_print_fault(&soap, stderr);
}
else
{
str = resultStr.getMobileCodeInfoResult;
std::cout << str << endl;
}
soap_destroy(&soap);
soap_end(&soap);
soap_done(&soap);
}
運行后如圖:

我們可以查看http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl,查看該xml文件可看到字符編碼是UTF8的,因此傳遞給接口的參數需要轉換到UTF8才可,ConvAnsiToUtf8()是轉換函數。gsoap 的 核心內部是入和出都是UTF8編碼的,由於中文是多字節的,所以將多字節的按照UTF8轉換,最終結果就是亂碼。正確的方式應該是:soap_set_mode(&soap,SOAP_C_MBSTRING);這樣中文便不會亂碼,可正常返回。
