gSOAP 2.8.5 用戶手冊
1 簡介
gSOAP工具基於編譯器技術爲C/C++提供自動的SOAP和XML數據綁定。(這句話很差理解,且向下看)。該工具使用自動生成代碼以及先進的映射方法,簡化了基於C/C++的SOAP/XML Web service和XML應用程序的開發。(有點靠譜了,能夠理解成該工具能夠幫助程序員完成協議底層的代碼)。大多數Web services工具採用以WSDL/SOAP爲中心的觀點,而且提供一組API,使用這些API必須使用相應的類庫來處理特定XML數據結構。這強迫用戶去適應該程序邏輯才能使用這些類庫,由於用戶在使用該特定廠商的API時必須編寫代碼去填充XML和抽取XML數據。這每每致使一個脆弱的解決方案,幾乎沒有數據一致性、類型安全和XML驗證的保證。(好了,損完別人了,下面開始自詡)。與其餘工具不一樣的是,gSOAP使用編譯器技術爲用戶隱藏了WSDL、SOAP、特定XML的實現細節,同時自動提供XML有效性驗證、內存管理和類型安全序列化,從而提供透明的解決方案。gSOAP工具可將原有的數據類型和用戶自定義的數據類型映射成等價的XML數據類型,反之亦然。所以,經過一個簡單的API獲得了完美的SOAP互操做性,從而可以使用用戶從WSDL/SOAP/XML的細節中解脫出來,集中精力處理應用程序邏輯。(主要仍是講了gSOAP能夠給用戶,即程序員,提供協議透明,經過什麼方式呢?經過自動生成的代碼)
gSOAP工具支持傳統的C/C++代碼(以及留有C接口的其餘編程語言)、嵌入式系統、那些和其餘SOAP程序共享計算資源和信息的實時SOAP/XML應用程序之間的集成,能夠跨平臺,適用不一樣的語言環境和穿透防火牆。(翻這段很累,還沒翻好)
gSOAP工具經常使用C/C++實現XML數據綁定。這意味着程序本地數據結構可被自動地用XML編碼,而不須要額外去編寫轉換代碼。該工具還爲了XML數據綁定生成XML模式,因此外部程序能夠基於該模式使用XML數據。(不懂,且往下看)
1.1 準備工做
使用gSOAP工具構建Web services應用程序或實現自動化XML數據綁定,你須要具有以下條件:
- C或C++編譯器
- 如想支持SSL(HTTPS)和壓縮,你還須要安裝OpenSSL、Zlib庫.這些庫適用於大多數平臺,同時一般也是已經安裝好的。
gSOAP是獨立的軟件,不須要安裝第三方軟件(除非你想使用OpenSSL或者你想從新構建soapcpp2工具,見下文)
從SourceForge獲取的gSOAP包在gsoap/bin目錄下有預構建的工具:(注:SourceForget是開源軟件開發者進行開發管理的集中式場所,也是全球最大開源軟件開發平臺和倉庫)
- wsdl2h :WSDL/模式導入和數據映射綁定工具。(注:該工具將wsdl轉換爲開發用的.h文件)
- soapcpp2 :存根/框架編譯器和代碼生成器。(注:該工具依據.h文件自動生成部分C/CPP語言代碼)
這兩個程序支持Windows、Linux和Mac OS 平臺,詳情參考README文件。
儘管gSOAP爲不一樣平臺準備了二進制格式的工具,但他們生成的代碼是等價的。這意味着生成的源代碼能夠移植到其餘平臺並進行本地化編譯。
若是你沒有該工具,或者你想從新構建,你須要:
- 一個C編譯器和Bison(或Yacc)來構建soapcpp2。(注Bison和Yacc也是一種編譯器)
- 一個C編譯器和Flex(或Lex)來構建soapcpp2。
- 一個C++編譯器來構建wsdl2h。
Bison和Flex是首選的。二者與gSOAP基於相同的開源標準發佈的。
- Bison 可今後處得到: http://www.gnu.org/software/bison
- Flex 可今後處得到: http://flex.sourceforge.net
gSOAP引擎能夠被構建成libgsoap.a和libgsoap++.a庫,後者支持SSL。參照README.txt的指示能夠看到如何經過gSOAP包裏的autoconf和automake構建與平臺無關的庫。或者,你將引擎的源代碼stdsoap2.c(或stdsoap2.cpp)直接編譯並連接進大家工程裏。(注:說明gSOAP提供兩種使用方式 ,一種編譯成動態連接庫,或者直接將源代碼編譯進工程)
gSOAP包中,在samples目錄下有不少例子。執行make命令能夠構建這些例子程序。這些例子同時也是用來展現gSOAP不一樣特性的。好比,在samples/mtom-streaming中,一個流式的MTOM附件服務端和客戶端程序展現高效的文件傳輸;在samples/webservice中,SSL-secure網絡服務端展現能夠爲Web流覽器和Web服務調用生成不一樣的內容。諸如此類,還有不少。
1.2 快速開始:開發一個Web Service客戶端應用程序
經過高級XML模式分析器和代碼生成器可實現XML數據綁定,這大大減小了構建Web Service程序的難度。wsdl2h工具導入一個或多個WSDL和XML模式能夠生成C/C++頭文件,該文件定義了Web Service操做以及C/C++數據類型。gsoapcpp2然手根據該頭文件生成XML序列化的數據類型、客戶端框架代碼(soapClient.cpp)和服務端框架代碼(soapServer.cpp)。
gSOAP編譯器也能夠生成WSDL定義文件,用來從頭實現一個服務。這個閉環可使Web services開發基於WSDL文件或者基於C/C++頭文件中的一系列選項,不須要用戶去分析Web服務細節。
你只須要遵循一些步驟執行命令行或Makefile(使用MSVC++ IDE的話參照sample目錄下的MSVC++例子)。例如,爲了生成計算器Web應用代碼,咱們經過命令行執行wsdl2h工具,從URL上的WSDL文件生成頭文件,這裏使用-o指定輸出文件名:
wsdl2h -o calc.h http://www.genivia.com/calc.wsdl
(注:在瀏覽器中訪問
http://www.genivia.com/calc.wsdl 能夠得到一個wsdl文件,在該命令行中,用此wsdl文件名替換連接也是能夠的)
這樣就生成了描述服務操做定義及數據類型定義的頭文件calc.h。接着能夠經過soapcpp2將該頭文件生成框架代碼或XML序列化例程。calc.h頭文件包含全部的說明,你可使用Doxygen(http://www.doxygen.org)來生成開發文檔。
使用wsdl2h生成的服務定義頭文件一樣包含如何調用服務的信息。
在這個例子中,咱們開發一個基於C++的計算器服務。默認狀況下,gSOAP假定咱們使用C++的STL。如不想使用STL,使用選項-s:
wsdl2h -s -o calc.h http://www.genivia.com/calc.wsdl
構建純C程序,使用-c:
wsdl2h -c -o calc.h http://www.genivia.com/calc.wsdl
到如今爲止,咱們尚未生成C/C++的存根。爲了生成它,咱們使用soapcpp2編譯器:
soapcpp2 -i -C -Iimport calc.h
選項-i指示咱們但願獲得C++代理和包含客戶端(服務端)代碼的對象。-C指示只生成客戶端對象(默認狀況下,gsoapcpp2同時生成客戶端和服務端對象)。選項-I指示須要從import目錄引入stlvector.h文件,以支持STL容器序列化,import目錄也在gSOAP包中。
假定咱們開發一個C++計算器客戶端:
wsdl2h -o calc.h http://www.genivia.com/calc.wsdl
soapcpp2 -i -C calc.h
(注:事實上執行第二行命令須要指定-I路徑,以下所示:其中紅色的文件是該步驟生成的)
./soapcpp2 -i -C -I/home/infor/renhc/gsoap/gsoap_2.8.5/gsoap-2.8/gsoap/import calc.h
[infor@s123 linux386]$ ls -ltr
total 3376
-rwxr-xr-x 1 infor app 2383149 Dec 6 11:46 wsdl2h
-rwxr-xr-x 1 infor app 818123 Dec 6 11:46 soapcpp2
-rw-r--r-- 1 infor app 5249 Dec 6 13:53 calc.wsdl
-rw-r--r-- 1 infor app 24316 Dec 6 14:42 calc.h-rw-r--r-- 1 infor app 7101 Dec 6 14:44 soapStub.h -rw-r--r-- 1 infor app 34463 Dec 6 14:44 soapH.h -rw-r--r-- 1 infor app 95689 Dec 6 14:44 soapC.cpp -rw-r--r-- 1 infor app 3573 Dec 6 14:44 soapcalcProxy.h -rw-r--r-- 1 infor app 12319 Dec 6 14:44 soapcalcProxy.cpp -rw-r--r-- 1 infor app 490 Dec 6 14:44 calc.sub.res.xml -rw-r--r-- 1 infor app 478 Dec 6 14:44 calc.sub.req.xml -rw-r--r-- 1 infor app 490 Dec 6 14:44 calc.pow.res.xml -rw-r--r-- 1 infor app 478 Dec 6 14:44 calc.pow.req.xml -rw-r--r-- 1 infor app 521 Dec 6 14:44 calc.nsmap -rw-r--r-- 1 infor app 490 Dec 6 14:44 calc.mul.res.xml -rw-r--r-- 1 infor app 478 Dec 6 14:44 calc.mul.req.xml -rw-r--r-- 1 infor app 490 Dec 6 14:44 calc.div.res.xml -rw-r--r-- 1 infor app 478 Dec 6 14:44 calc.div.req.xml -rw-r--r-- 1 infor app 490 Dec 6 14:44 calc.add.res.xml -rw-r--r-- 1 infor app 478 Dec 6 14:44 calc.add.req.xml
咱們使用生成的soapcalcProxy類和XML命名空間映射表calc.nsmap來訪問Web服務。該soapcalcProxy類是調用服務的一個代理。
#include "soapcalcProxy.h"
#include "calc.nsmap"
main()
{
calcProxy service;
double result;
if (service.add(1.0, 2.0, result) == SOAP_OK)
std::cout << "The sum of 1.0 and 2.0 is " << result << std::endl;
else
service.soap_stream_fault(std::cerr);
}
接下來咱們編譯並連接生成的soapC.cpp和soapcalcProxy.cpp,以及動態連接庫-lgsoap++(若是你沒有安裝該庫,能夠將stdsoap2.cpp引入到你的代碼)。(注:上面就構建完了基於C++的客戶端)
假定咱們開發的是C語言客戶端,那麼咱們能夠這樣:
wsdl2h -c -o calc.h http://www.genivia.com/calc.wsdl
soapcpp2 -C calc.h
代碼須要遵循C語言規範:
#include "soapH.h"
#include "calc.nsmap"
main()
{
struct soap *soap = soap_new();
double result;
if (soap_call_ns__add(soap, 1.0, 2.0, &result) == SOAP_OK)
printf("The sum of 1.0 and 2.0 is %lg\n", result);
else
soap_print_fault(soap, stderr);
soap_end(soap);
soap_free(soap);
}
這個計算器的例子是至關簡單,此處只用來講明開發過程。這與大型程序開發流程是類似的。更多的能夠參考sample目錄下的例子。
1.3 快速開始:開發Web 服務
開發服務端程序也很簡單。這裏咱們使用CGI,由於這是個簡單的機制。(注:CGI英文全拼是Common Gateway Interface,即通用網關接口)。這不是首選的部署機制,由於CGI很是慢並且無國籍,咱們建議開發獨立的gSOAP HTTP/HTTPS服務(參照本節最後部分註解)或者使用Apache組件,再或者IIS(在gSOAP包的gsoap/mod_gsoap目錄下)。
假設咱們開發一個基於CGI的服務,該服務返回GMT時間。CGI能夠很是簡單的將服務發佈到Web站點。
咱們以一個gSOAP頭文件開始本例,currentTime.h包含服務的定義。若是咱們能獲得WSDL文件,咱們可使用wsdl2h獲得這樣的頭文件。若是沒有WSDL,你可使用C/C++重頭定義一個頭文件,而後使用gSOAP工具生成源代碼和WSDL。
咱們的currentTime服務只有一個輸出參數,就是當前時間,在currentTime.h文件中定義以下:
// File: currentTime.h
//gsoap ns service name: currentTime
//gsoap ns service namespace: urn:currentTime
//gsoap ns service location: http://www.yourdomain.com/currentTime.cgi
int ns__currentTime(time_t& response);
注意,咱們關聯一個XML命名空間前綴「ns」和命名空間urn:currentTime到WSDL服務和SOAP/XML信息。gSOAP工具使用特殊轉化方式獲得標識符名字:命名空間前綴後跟兩個下劃線。之因此如此處理命名空間,是爲了不命名衝突。命名空間前綴「ns」經過「//gsoap」指令綁定到
urn:currentTime命名空間。
//gsoap指令用來設置服務屬性,在本例中有
name、
namespace和
location。
CGI的服務實現須要在soap上下文上調用soap_serve,soap環境經過soap_new建立。服務的具體實現就像一個函數,該函數由RPC調度器使用soap_servey調用:
// File: currentTime.cpp
#include "soapH.h" // include the generated declarations
#include "currentTime.nsmap" // include the XML namespace mappings
int main()
{
// create soap context and serve one CGI-based request:
return soap_serve(soap_new());
}
int ns__currentTime(struct soap *soap, time_t& response)
{
response = time(0);
return SOAP_OK;
}
注意,咱們傳遞帶有soap上下文信息的soap結構給服務例程。這很是方便於肯定鏈接的性能,還可使用soap_malloc(soap, num_bytes)動態申請空間,以及在服務結束時動態刪除他們。
咱們運行soapcpp2編譯器,生成服務端代碼:
soapcpp2 -S currentTime.h
接着編譯獲得CGI二進制程序:
c++ -o currentTime.cgi currentTime.cpp soapC.cpp soapServer.cpp stdsoap2.cpp
stdsoap2.cpp能夠在gsoap目錄下找到。或者,若是你安裝了gsoap,你能夠選擇連接libgsoap++庫,就不用使用
stdsoap2.cpp源碼了,像這樣:
c++ -o currentTime.cgi currentTime.cpp soapC.cpp soapServer.cpp -lgsoap++
爲了激活這個服務,將生成的
currentTime.cgi二進制程序拷貝到bin-cgi目錄下,並賦以恰當的權限。
soapcpp2工具生成WSDL描述文件currentTime.wsdl。你可使用這個WSDL發佈你的服務。你不須要使用這個WSDL去開發客戶端。由於你已經有了
currentTime.h,使用soapcpp2的-C選項能夠生成客戶端代碼。(注:參考1.2節)
CGI能夠方便的經過標準I/O交換信息。所以,咱們使用自動生成的請求樣例代碼來測試:
./currentTime.cgi < currentTime.currentTime.req.xml
這樣,獲得的返回也是SOAP XML。
上面的過程一樣適用於純C語言。只須要在soapcpp2的-S選項後添加-c選項就能夠生成ANSI C代碼。固然,在C語言中咱們使用指針而不是引用,同時
currentTime.h文件也必須只能使用C類型。
另外還有一個更優雅的C++服務端實現:使用soapcpp2的-i(或-j)選項生成C++的客戶端和服務端的服務類,使用這個類同時能夠構建客戶端也能夠構建服務端。使用這個選項就不須要
soapClient.cpp和
soapServer.cpp了,由於咱們有了客戶端和服務端的類實現:
soapcpp2 -i -S currentTime.h
這樣就會生成
soapcurrentTimeService.h和
soapcurrentTimeService.cpp文件,以及輔助文件
soapStub.h和
currentTime.nsmap。
使用
currentTimeService對象,咱們重寫CGI服務:
// File: currentTime.cpp
#include "soapcurrentTimeService.h" // include the proxy declarations
#include "currentTime.nsmap" // include the XML namespace mappings
int main()
{
// create server and serve one CGI-based request:
currentTimeService server;
return server.serve();
}
int currentTimeService::currentTime(time_t& response)
{
response = time(0);
return SOAP_OK;
}
編譯:
c++ -o currentTime.cgi currentTime.cpp soapC.cpp soapcurrentTimeService.cpp -lgsoap++
接着安裝CGI二進制文件。安裝方法請查閱Web服務文檔。
若是想在8080端口上以迭代方式運行服務,可使用:
return currentTimeService.run(8080);
想實現線程服務,請查看7.2.4節。該節講述了經過多個線程來處理多個SO來請求。線程池也可使用。
7.2.7節有更多的服務端類的描述。7.1.4節有更多的客戶端代理類的描述。
1.4 快速開始: XML數據綁定(待續)
1.5 特點概述(待續)
2 符號轉換約定(待續)
3 版本2.4(包括以前的版本)與版本2.5的區別(待續)
4 版本2.1(包括以前的版本)與版本2.2的區別(待續)
5 gSOAP版本1.X和版本2.X之間的區別(待續)
6 互操做性(待續)
7 快速用戶指南
這個用戶指南提供快速的方式來使用gSOAP。理解本節須要對SOAP協議有一個基本的理解,還須要熟悉C/C++。若是你對SOAP協議沒有深刻的瞭解,你也可使用gSOAP開發 C/C++的基於SOAP的C/S程序,不過,前提是客戶端和服務端一致而且只在小組內通訊(即,你不須要擔憂其餘SOAP實現的互操做性)。本節開始說明gSOAP Web服務端和客戶端的實現,進而說明與其餘SOAP實現的互操做性,好比Apache Axis、SOAP::Lite和.NET。這須要瞭解SOAP和WSDL協議細節。
7.1 如何構建SOAP/XML 客戶端
通常狀況下,SOAP客戶端程序的實現須要一個存根(也稱作服務代理),該存根提供客戶端調用服務的操做。存根的主要職責是處理參數,經過網絡向指定的服務端發送請求,並等待應答,應答到來後再將參數解析出來。客戶端只須要調用存根提供的例程,就像調用本地的函數同樣。手工編寫存根例程是很是麻煩的,特別是當輸入輸入參數涉及到複雜數據結構,如對象、結構體、容器、數組及指針指向的圖形結構。幸運的是,gSOAP wsdl2h WSDL解析工具和soapcpp2存根生成器和序列化代碼生成器可自動開發Web Service客戶端和服務端。
soapcpp2生成必要的膠水代碼(也稱做存根或框架)來構建客戶端和服務端。soapcpp2輸入一個註解服務的C/C++頭文件。該頭文件能夠經過wsdl2h解析工具生成,該工具須要一個WSDL文檔。
考慮下面的命令:
wsdl2h -o calc.h http://www.genivia.com/calc.wsdl
這將生成一個C++頭文件,該文件描述了服務的定義。