用gSoap開發 C/C++ 客戶端 連線Web Service
轉載地址: http://blog.csdn.net/zhaiwenjuan/article/details/6590941
少了個安裝步驟
1、下載解壓gsoap檔案
2、安裝所需的相關工具
sudo apt-get install g++
sudo apt-get install bison
sudo apt-get install flex
suod apt-get install openssl
sudo apt-get install libssl-dev
sudo apt-get install libgtk2.0-dev libglib2.0-dev
3、./configure
4、make & make install
5、完成安裝
在Linux下,利用gSoap開發Web Service C/C++客戶端
2010-11-24 09:59
一. 開發環境準備
1. 從gSoap官方網站http://gsoap2.sourceforge.net 下載gSoap工具包。
本例下載的是2.7.15的版本。
2. 根據說明文件(README)配置安裝gSoap工具包。
說明: 一般下載的gSoap工具包中已經包含了生成Web Service客戶端需要用到的兩個工具(可執行檔案):wsdl2h和soapcpp2,一般在gsoap/bin/linux386下。只是預設情況下,wsdl2h並不支援SSL,即無法訪問HTTPS站點,且這兩個工具的版本一般也要低於所在gSoap工具包的版本。
所以如果想要支援SSL等更多功能,就需要自己重新配置編譯該gSoap工具包,以生成新的sdl2h和soapcpp2。
反之,如果下載的gSoap工具包中自帶的wsdl2h和soapcpp2已經滿足了你的需求,就可以不必再配置編譯gSoap工具包了;而是直接使用工具包自帶的wsdl2h和soapcpp2。
二. 開發linux下Web Service C/C++客戶端
這裡,我們直接採用gSoap工具包自帶的wsdl2h和soapcpp2工具。
1. 基本流程
從Web服務提供者處獲取Web Service的WSDL檔案,通常是一個URL,
如:http://www.cs.fsu.edu/~engelen/calc.wsdl
當然也可以是一個WSDL形式的XML檔案。
2. 使用gSoap工具wsdl2h,根據WSDL生成一個C/C++語法結構的標頭檔案。
如:wsdl2h -s -o calc.h http://www.cs.fsu.edu/~engelen/calc.wsdl
這一步將會得到一個頭檔案,如:calc.h
該步的目的:實現WSDL檔案到.h檔案的資料對映。
3. 使用gSoap的預編譯器soapcpp2,根據上一步得到的標頭檔案來生成存根檔案(soapStub.h)和客戶端程式碼框架。
如:soapcpp2 -i -x -C -L calc.h
這一步將會得到幾個. nsmap、.h和.cpp檔案,如:calc.nsmap、soapC.cpp、soapH.h、soapStub.h、soapcalcProxy.cpp、soapcalcProxy.h
該步的目的:生成相應的底層通訊程式碼。
4. 實現客戶端例程
在這一步可以簡單地編寫一個main函式,如:(注意包含的標頭檔案)
#include "calc.nsmap"
#include "soapcalcProxy.h" //該標頭檔案已經包含了soapH.h
int main(void)
{
printf("very good!\n");
calcProxy service;
{
double result;
if(service.pow(2, 10, result) == SOAP_OK)
{
std::cout << "The value of 2^10 is " << result << std::endl;
}
}
return 0;
}
5. 用gcc編譯客戶端,生成可執行程式碼
編譯需要的檔案有:第3步生成的所有檔案、第4步編寫的main函式所在的檔案,以及gsoap目錄下的stdsoap2.h和stdsoap2.cpp檔案共9個檔案。
如:calc.nsmap、soapC.cpp、soapH.h、soapStub.h、soapcalcProxy.cpp、soapcalcProxy.h、stdsoap2.cpp、stdsoap2.h、main.cpp。
三、注意事項
注1 :wsdl2h的用法(WSDL/schema 解析和程式碼生成器)
wsdl2h [opt] 標頭檔案名 WSDL檔名或URL
wsdl2h常用選項
-o 檔名,指定輸出標頭檔案
-n 名空間字首 代替預設的ns
-c 產生純C程式碼,否則是C++程式碼
-s 不要使用STL程式碼
-t 檔名,指定type map檔案,預設為typemap.dat
-e 禁止為enum成員加上名空間字首
type map檔案用於指定SOAP/XML中的型別與C/C++之間的轉換規則,比如在wsmap.dat裡寫。
在本例中,使用的是:wsdl2h -s -o calc.h http://www.cs.fsu.edu/~engelen/calc.wsdl
引數s就表示生成不帶STL的C/C++語法結構的標頭檔案calc.h。
如果不用s就會生成帶STL的標頭檔案,這樣,在後邊的編譯中需要加入STL的頭
stlvector.h,位於:gsoap/import/目錄下。
注2 :soapcpp2的用法(編譯和程式碼生成器)
soapcpp2 [opt] 標頭檔案名
soapcpp2常用選項
-C 僅生成客戶端程式碼
-S 僅生成伺服器端程式碼
-L 不要產生soapClientLib.c和soapServerLib.c檔案
-c 產生純C程式碼,否則是C++程式碼(與標頭檔案有關)
-I 指定import路徑(見上文)
-x 不要產生XML示例檔案
-i 生成C++封裝(代理),客戶端為xxxxProxy.h(.cpp),伺服器端為xxxxService.h(.cpp)。
本例中,使用的是:soapcpp2 -i -x -C -L calc.h
注3 :gSoap工具wsdl2和soapcpp所生成檔案的簡單分析
(1) wsdl2生成的具有C/C++語法結構的標頭檔案,其作用就是:將XML語法結構的WSDL檔案對映為C/C++語法結構的.h檔案;併為下一步做準備。
(2) soapcpp(採用引數:-i -x -C -L)生成的檔案共有6個檔案:PlayerBeanPortBinding.nsmap、soapC.cpp、soapH.h、 soapPlayerBeanPortBindingProxy.cpp、soapPlayerBeanPortBindingProxy.h、 soapStub.h。
a. PlayerBeanPortBinding.nsmap檔案
該檔案的作用:An XML-to-C/C++ namespace mapping table,即WSDL檔案與生成的客戶端程式碼框架的一個名字空間的對映表。
b. soapStub.h
該檔案就是直接由wsdl2生成的標頭檔案轉化而來,它詳細定義了WSDL所描述的各項服務和資料結構。
它是soap的存根檔案,定義了由wsdl2生成的標頭檔案裡對應的遠端呼叫模型(RPC)。
c. soapPlayerBeanPortBindingProxy.和soapPlayerBeanPortBindingProxy.cpp
這兩個檔案是客戶端程式碼的一個簡單封裝,它封裝了底層通訊,並向外提供一個很簡單的介面,該介面展示了使用者能夠使用的所有服務(由WSDL所描述)。
d. soapH.h和soapC.cpp
這個兩個檔案是soap的序列和反序列化程式碼,
注4 :設定字元編碼
在利用gSoap編寫Web Service客戶端和伺服器端的程式時,需要設定其編碼
方式。介面為:soap_set_mode,其實它是就是一個巨集:
#define soap_set_mode(soap, n) ((soap)->imode |= (n), (soap)->omode |= (n))
如果要設定為UTF8
可以這樣呼叫:soap_set_mode(&soap, SOAP_C_UTFSTRING);
詳細資訊可參考該巨集所在檔案:stdsoap2.h
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/gogor/archive/2010/09/20/5896135.aspx
多的不贅述 以上文章已經寫得很明白了 ,只是提醒一下 著重看一下 加粗的字型的內容!!!
但是有一點上面沒有寫過 所以在自己的開發中遇到麻煩了
注意 此博文最後一段 注4 的內容
設定連線編碼為utf8
然而 還有更重要的一點 我們是用代理檔案中存在的代理去呼叫介面的 所以代理也需要設定為utf8
如下:
int iRet = 0;
struct soap userinfoSoap;
soap_init( &userinfoSoap );
soap_set_mode( &userinfoSoap, SOAP_C_MBSTRING );
struct _ns1__ismspSendMultSms helloWorld;
struct _ns1__ismspSendMultSmsResponse helloWorldResponse;
const char *pcAddr = "http://192.168.2.107:**********";
ns2__IbnSms ibnSMS;
ibnSMS.loginName = "賬號";
ibnSMS.loginPwd = "密碼";
ibnSMS.msgContent = "漢字" ; //"對了嗎?";// "對了嗎?";// ( char* )str.data( );
//ibnSMS.msgContent = const_cast<char*>();
ibnSMS.mobileNumber = "152*******";
helloWorld.args0 = &ibnSMS;
//helloWorld.soap = &userinfoSoap;
iSmsSendManagerSoap11BindingProxy smsProxy( SOAP_C_UTFSTRING );
cout << "read SMS" << endl;
iRet = smsProxy.ismspSendMultSms( pcAddr, "", &helloWorld, helloWorldResponse );
cout << SOAP_OK << " " << iRet << endl;
if ( iRet != 0 )
{
printf( "讀取資料失敗" );
}
else
{
printf( "讀取資料成功:%s", helloWorldResponse );
}
soap_destroy( &userinfoSoap );
soap_end( &userinfoSoap );
soap_done( &userinfoSoap );
getchar( );