小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

gSOAP學(xué)習(xí)筆記

 希望蠟炬 2013-01-21
目錄
一、基本概念
  1.1 關(guān)于SOAP
  1.2 關(guān)于gSOAP
  1.3 gSOAP編譯器(命令行工具)
    1.3.1 wsdl2h
    1.3.2 socapcpp2
二、gSOAP開發(fā):Web Service服務(wù)端
三、gSOAP開發(fā):Web Service客戶端
四、參考資料

一、基本概念

1.1 關(guān)于SOAP

SOAP(Simple Object Access Protocol),即簡單對(duì)象訪問協(xié)議,是在分布式的環(huán)境中交換數(shù)據(jù)的簡單協(xié)議,以XML作為數(shù)據(jù)傳送語言。
SOAP有兩種工作模式,一種是RPC(Remote Procedure Call),另一種是Message-Oriented。MO可以利用XML來交換結(jié)構(gòu)更復(fù)雜的數(shù)據(jù)。RPC模式的SOAP可以理解為這樣一個(gè)開發(fā)協(xié)議:SOAP=RPC+HTTP+XML,具有以下特點(diǎn):

  • 采用HTTP作為通信協(xié)議,采用客戶/服務(wù)模式;
  • RPC作為統(tǒng)一的遠(yuǎn)程方法調(diào)用途徑;
  • 傳送的數(shù)據(jù)使用XML格式。

看一個(gè)簡單的請(qǐng)求及回復(fù)SOAP數(shù)據(jù)(真實(shí)數(shù)據(jù)):

POST /wpsoap/ HTTP/1.1
Host: 127.0.0.1:10240
User-Agent: gSOAP/2.7
Content-Type: text/xml; charset=utf-8; action=""
Content-Length: 480
Connection: close
SOAPAction: ""
 
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas./soap/envelope/" xmlns:SOAP-ENC="http://schemas./soap/encoding/" xmlns:xsi="http://www./2001/XMLSchema-instance" xmlns:xsd="http://www./2001/XMLSchema" xmlns:ns1="http://www./wpsoap/" xmlns:ns2="urn:nszfpt"><SOAP-ENV:Body><ns2:login><req><username>admin</username><password>3.14159</password></req></ns2:login></SOAP-ENV:Body></SOAP-ENV:Envelope>
HTTP/1.1 200 OK
Server: gSOAP/2.7
Content-Type: text/xml; charset=utf-8; action=""
Content-Length: 555
Connection: close
 
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas./soap/envelope/" xmlns:SOAP-ENC="http://schemas./soap/encoding/" xmlns:xsi="http://www./2001/XMLSchema-instance" xmlns:xsd="http://www./2001/XMLSchema" xmlns:wpsoap="urn:nszfpt"><SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas./soap/encoding/"><wpsoap:tagRspLogin><rsp><retCode>0</retCode><retMessage>login ok!</retMessage></rsp><session>01234567890</session></wpsoap:tagRspLogin></SOAP-ENV:Body></SOAP-ENV:Envelope>

這東西非常的復(fù)雜,我僅僅記錄一下使用到的部分。

1.2 關(guān)于gSOAP

引用:http://blog.csdn.net/darkone/archive/2006/12/14/1442525.aspx
gSOAP編譯工具提供了一個(gè)SOAP/XML 關(guān)于C/C++ 語言的實(shí)現(xiàn),
從而讓C/C++語言開發(fā)web服務(wù)或客戶端程序的工作變得輕松
了很多。絕大多數(shù)的C++web服務(wù)工具包提供一組API函數(shù)類庫
來處理特定的SOAP數(shù)據(jù)結(jié)構(gòu),這樣就使得用戶必須改變程序
結(jié)構(gòu)來適應(yīng)相關(guān)的類庫。與之相反,gSOAP利用編譯器技術(shù)提
供了一組透明化的SOAP API,并將與開發(fā)無關(guān)的SOAP實(shí)現(xiàn)細(xì)節(jié)
相關(guān)的內(nèi)容對(duì)用戶隱藏起來。gSOAP的編譯器能夠自動(dòng)的將用
戶定義的本地化的C或C++數(shù)據(jù)類型轉(zhuǎn)變?yōu)榉蟈ML語法的數(shù)據(jù)
結(jié)構(gòu),反之亦然。這樣,只用一組簡單的API就將用戶從SOAP
細(xì)節(jié)實(shí)現(xiàn)工作中解脫了出來,可以專注與應(yīng)用程序邏輯的實(shí)
現(xiàn)工作了。gSOAP編譯器可以集成C/C++和Fortran代碼(通過
一個(gè)Fortran到C的接口),嵌入式系統(tǒng),其他SOAP程序提供
的實(shí)時(shí)軟件的資源和信息;可以跨越多個(gè)操作系統(tǒng),語言環(huán)
境以及在防火墻后的不同組織。
	gSOAP使編寫web服務(wù)的工作最小化了。gSOAP編譯器生成
SOAP的代碼來序列化或反序列化C/C++的數(shù)據(jù)結(jié)構(gòu)。gSOAP包
含一個(gè)WSDL生成器,用它來為你的web服務(wù)生成web服務(wù)的解
釋。gSOAP的解釋器及導(dǎo)入器可以使用戶不需要分析web服務(wù)
的細(xì)節(jié)就可以實(shí)現(xiàn)一個(gè)客戶端或服務(wù)端程序。

照我理解,gSOAP可以為我們生成soap服務(wù)器端+客戶端代碼的框架,我們只需實(shí)現(xiàn)具體的接口函數(shù)即可。而生成代碼的工具就是上面文中提到的“gSOAP編譯器”。

1.3 gSOAP編譯器(命令行工具)

1.3.1 wsdl2h

此工具用來從WSDL文件生成c/c++頭文件。

wsdl2h -o 頭文件名 WSDL文件名或URL
常用的其它參數(shù):
-o 文件名,指定輸出頭文件
-n 名空間前綴 代替默認(rèn)的ns
-c 產(chǎn)生純C代碼,否則是C++代碼
-s 不要使用STL代碼
-t 文件名,指定type map文件,默認(rèn)為typemap.dat
-e 禁止為enum成員加上名空間前綴

1.3.2 socapcpp2

此工具用來從頭文件,生成SOAP服務(wù)器及客戶端代碼,還包括WSDL、測試用XML數(shù)據(jù)。

soapcpp2 頭文件
常用選項(xiàng)
-C 僅生成客戶端代碼
-S 僅生成服務(wù)器端代碼
-L 不要產(chǎn)生soapClientLib.c和soapServerLib.c文件
-c 產(chǎn)生純C代碼,否則是C++代碼(與頭文件有關(guān))
-I 指定import路徑(見上文)
-x 不要產(chǎn)生XML示例文件
-i 生成C++包裝,客戶端為xxxxProxy.h(.cpp),服務(wù)器端為xxxxService.h(.cpp)。

二、gSOAP開發(fā):Web Service服務(wù)端

開發(fā)服務(wù)器程序,需使用gSOAP生成服務(wù)器端代碼框架。我們有兩種做法:

  1. 編寫WSDL,使用wsdl2h生成頭文件,再soapcpp2生成框架代碼;
  2. 編寫頭文件,使用soapcpp2生成框架代碼;

這兩種方式,結(jié)果是一樣的,最終都有產(chǎn)生頭文件,并生成代碼。不同在于,在項(xiàng)目的開發(fā)中需要維護(hù)的文件不同,前者是需要維護(hù)WSDL文件,后者維護(hù)頭文件。

我個(gè)人覺得第二種方式更好用,不僅僅是少了個(gè)步驟,而是WSDL的語法太難寫了,有點(diǎn)XSD的味道。而頭文件的編寫,更接近于程序員的思考方式,比如定義消息結(jié)構(gòu),定義接口名稱等。

gSOAP是非常智能的,它利用C/C++的注釋來獲取信息,所以在手工編寫的頭文件中,注釋是用用處的,常以// gsoap 名字空間 …開頭。做為學(xué)習(xí),我準(zhǔn)備為php blog程序wordpress寫一個(gè)web service接口,名字叫wpsoap。

我開始寫頭文件(wpSoap.h)了,出于學(xué)習(xí)目的,我僅實(shí)現(xiàn)了兩個(gè)接口:一是用戶登陸;一是日志發(fā)布。

/**
 * @file wpsoap.h
 * @brief 為wordpress2.7提供web service接口
 *
 *  "http://gsoap"開頭行,請(qǐng)勿刪除.
 * 
 *  1. 通過此文件生成WSDL 及 服務(wù)端代碼
 * 
 *    >mkdir -p srvSrcFromH
 *    >cd srvSrcFromH
 *    >soapcpp2 -L -S "wpsoap.h" -I /path/to/gsoap-2.8/gsoap/import/
 * 
 *  2. 通過WSDL生成客戶端代碼
 * 
 *    >mkdir -p clientSrcFromWSDL
 *    >cd clientSrcFromWSDL
 *    >wsdl2h.exe  -o wpsoap.h ../srvSrcFromH/wpsoap.wsdl -I /path/to/gsoap-2.8/gsoap/import/
 *    >soapcpp2 -L -C wpsoap.h -I /path/to/gsoap-2.8/gsoap/import/
 *
 * @author pansunyou@gmail.com
 * @version 1.0
 * @date 2010-12-27
*/
 
//gsoap wpsoap service name: wpsoap
//gsoap wpsoap service namespace: http://www./wpsoap/
//gsoap wpsoap service location: http://192.168.0.187:10240/wpsoap/
//gsoap wpsoap service encoding: encoded
//gsoap wpsoap schema namespace: urn:nszfpt
 
#import "stlvector.h"
 
//通用回復(fù)
class wpsoap__tagCommResponse
{
       int                  retCode                 ;      //回復(fù)碼
       std::string retMessage           ;      //回復(fù)消息
};
 
//[請(qǐng)求]用戶登陸
class wpsoap__tagReqLogin
{
    std::string username              ;      //用戶名
    std::string password        ;      //密碼名文
};
 
//[答復(fù)]用戶登陸
class wpsoap__tagRspLogin
{
    wpsoap__tagCommResponse rsp    ;      //通用回復(fù)
       std::string session                 ;      //會(huì)話標(biāo)識(shí)
};
 
//[接口]登陸接口
int wpsoap__login(wpsoap__tagReqLogin req, wpsoap__tagRspLogin& rsp);
 
 
//[請(qǐng)求]發(fā)布日志
class wpsoap__tagReqPost
{
    std::string title         ;      //標(biāo)題
    std::string body              ;      //正文
};
 
//[答復(fù)]發(fā)布日志
class wpsoap__tagRspPost
{
    wpsoap__tagCommResponse rsp    ;      //通用回復(fù)
};
 
//[接口]發(fā)布日志接口
int wpsoap__post(wpsoap__tagReqPost req, wpsoap__tagRspPost& rsp);

在接口中,我使用到了自定義的消息結(jié)構(gòu)wp_soap_tag*,這里的wpsoap__前綴是必須的,這樣soapcpp2才能為我們生成正確的代碼。

之后,我使用soapcpp2生成服務(wù)端代碼框架:

@echo off
@set path=%cd%\..\..\contrib\gsoap-2.8\gsoap\bin\win32\;%path%
 
mkdir srvSrcFromH 2>nul
cd srvSrcFromH
soapcpp2.exe -L -S ..\res\wpSoap.h -I ..\..\..\contrib\gsoap-2.8\gsoap\importpause

要編譯出服務(wù)程序,有這些代碼還不夠,還需要自己寫兩個(gè)文件,一個(gè)用來寫main函數(shù),一個(gè)用來寫wpsoap的接口函數(shù)(當(dāng)然可以放在一個(gè)文件里)。最終我的服務(wù)器程序有以下文件:(另外,還需要gsoap目錄下的stdsoap2.cpp,因?yàn)槲野阉幾g為靜態(tài)庫了,所以這里沒列出來。)

D:\wpSoapServer
|   makeSrc.bat
|   wpsoapimpl.cpp                //這里實(shí)現(xiàn)了soapStub.h給出的接口
|   wpsoapsrv.cpp                  //這里是main函數(shù)開始的地方
+---res
|       wpSoap.h
\---srvSrcFromH
        soapC.cpp
        soapH.h
        soapServer.cpp
        soapStub.h
        soapwpsoapObject.h
        wpsoap.login.req.xml
        wpsoap.login.res.xml
        wpsoap.nsmap
        wpsoap.post.req.xml
        wpsoap.post.res.xml
        wpsoap.wsdl
        wpsoap.xsd

每次我修改了res/wpSoap.h后,我就運(yùn)行一下makeSrc.bat,自動(dòng)重新生成srvSrcFromH目錄里的所有東西,并且這個(gè)目錄里的所有代碼是不需要手工維護(hù)的(除非有特殊需要)。

在服務(wù)器代碼中,我僅實(shí)現(xiàn)了以下兩個(gè)函數(shù)(wpsoapimpl.cpp):

int wpsoap__login(struct soap*, wpsoap__tagReqLogin req, wpsoap__tagRspLogin &rsp);
int wpsoap__post(struct soap*, wpsoap__tagReqPost req, wpsoap__tagRspPost &rsp);

wpsoapsrv.cpp里的代碼僅僅是調(diào)用gSOAP產(chǎn)生的代碼來建立socket服務(wù)器,基本不需維護(hù)。gSOAP是線程安全的,可以將請(qǐng)求分配到線程池內(nèi)實(shí)現(xiàn)高效服務(wù),但我僅為了走通gSOAP的使用流程,沒有這樣使用。

具體做法可以參考:http://www.cs./~engelen/soapdoc2.html

三、gSOAP開發(fā):Web Service客戶端

客戶端代碼本來也是可以通過為服務(wù)端編寫的頭文件生成的,但是為了真實(shí)一點(diǎn),假設(shè)我無法獲取服務(wù)器開發(fā)時(shí)使用的頭文件,僅僅有個(gè)公開的WSDL文件,就是上面產(chǎn)生的srvSrcFromH /wpsoap.wsdl。

我用這個(gè)腳本來生成客戶端框架代碼:

@echo off
@set path=%cd%\..\..\contrib\gsoap-2.8\gsoap\bin\win32\;%path%
 
mkdir clientSrcFromWSDL 2>nul
cd clientSrcFromWSDL
wsdl2h.exe -o wpsoap.h ..\..\wpSoapServer\srvSrcFromH\wpsoap.wsdl
soapcpp2.exe -L -C wpsoap.h -I ..\..\..\contrib\gsoap-2.8\gsoap\importpause

加上我測試用的代碼wpsoapclient.cpp,以及gosap目錄里的stdsoap2.cpp,我有了如下文件:

D:\wpSoapClient
|   makeSrc.bat
|   wpsoapclient.cpp
\---clientSrcFromWSDL
        soapC.cpp
        soapClient.cpp
        soapH.h
        soapStub.h
        soapwpsoapProxy.h
        wpsoap.h
        wpsoap.login.req.xml
        wpsoap.login.res.xml
        wpsoap.nsmap
        wpsoap.post.req.xml
        wpsoap.post.res.xml

客戶端代碼非常少(僅僅是實(shí)現(xiàn),容錯(cuò)之類的都未考慮):

/**
 * @file wpsoapclient.cpp
 * @brief 訪問wpsoap服務(wù)
 *
 * 調(diào)用wpsoap的客戶端示例代碼
 *
 * @author pansunyou@gmail.com
 * @version 1.0
 * @date 2010-12-27
*/
 
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstdlib>
#include <string>
#include "clientSrcFromWSDL/soapStub.h"
#include "clientSrcFromWSDL/soapwpsoapProxy.h"
#include "clientSrcFromWSDL/wpsoap.nsmap"
 
using namespace std;
 
int main(int argc, char*argv[])
{
  wpsoap wpsoapClient;
  if (argc==2)
    wpsoapClient.endpoint = argv[1];
 
  //1. 登陸
  string username = "admin";
  string password = "3.14159";
  int r = 0;
 
  ns2__tagReqLogin req;
  req.username = username;
  req.password = password;
  _ns2__login ns2__login;
  ns2__login.req = &req;
  _ns2__tagRspLogin rsp;
  r = wpsoapClient.__ns1__login(&ns2__login, &rsp);
  if (r!=0)
  {
    fprintf(stderr, "調(diào)用soap接口失敗!\n");
    return -1;
  }
 
  if (0!=rsp.rsp->retCode)
  {
    printf("登陸失敗 retCode=%d, retMessage=%s\n",
		rsp.rsp->retCode, 
		rsp.rsp->retMessage.c_str());
    return -1;
  }
  printf("登陸成功! [session=%s]\n",
	rsp.session.c_str());
 
        
  ns2__tagReqPost reqPost;
  reqPost.body = "post article by wpsoap!";
  reqPost.title = "hello, wpsoap!";
 
  _ns2__post ns2__post;
  ns2__post.req = &reqPost;
  _ns2__tagRspPost ns2__tagRspPost;
  r = wpsoapClient.__ns1__post(&ns2__post, 
	&ns2__tagRspPost);
  if (r!=0)
  {
    fprintf(stderr, "調(diào)用soap接口失敗!\n");
    return -1;
  }
 
  if (0!=rsp.rsp->retCode)
  {
    printf("發(fā)布日志失敗 retCode=%d, 
		retMessage=%s\n",
		rsp.rsp->retCode, 
		rsp.rsp->retMessage.c_str());
    return -1;
  }
  printf("日志發(fā)布成功! [retMessage=%s]\n", 
  rsp.rsp->retMessage.c_str());
  
  return 0;
}

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多