我的gsoap創(chuàng)建客戶端網絡代理過程

2017年06月11日16:42:58

創(chuàng)新互聯建站主要從事網站制作、成都做網站、網頁設計、企業(yè)做網站、公司建網站等業(yè)務。立足成都服務朔城,10年網站建設經驗,價格優(yōu)惠、服務專業(yè),歡迎來電咨詢建站服務:13518219792

這幾天做了一個售電接口(windows平臺下),包括webservice服務(C#)、webservice動態(tài)庫、客戶端dll(C++)、客戶端gsoap代理。軟件結構如下:

clientDLL(客戶端機器)---->gsoapProxy(客戶端機器)------>webservice(服務器)--->webserviceDLL(服務器)---->HSM(加密機)

【強調一下前提,webservice服務是用vs2010創(chuàng)建的web工程,而client是C/C++寫的,這里主要介紹如何使用gsoap代理client請求】

由于客戶端和服務器不是在同一臺機器上,所以使用直接動態(tài)調用dll已不可能。C/C++要通過網絡去連接服務器,將函數參數傳輸到webservice的對應函數接口中,就必然要使用某種工具來將函數參數轉換到網絡格式傳輸到server,gsoap就是這種強大的工具。gsoap不僅可以代理客戶端請求,還可以代理服務端(本次只使用其作為客戶端代理)。雖然其已經盡可能做到簡單易用,但是我在網絡上搜索了好多文章,都是教到生成出文件為止,而如何使用生成出的文件,都是不甚了了。所以我將整個使用過程記錄下來,方便以后借鑒。

(一)  下載gsoap軟件,網上搜一下,去官方下,然后解壓出來,一定要看是否解壓完全,在其根目錄下有3個文件stdsoap2.h、stdsoap2.cpp 、stdsoap2.c,這個后面要用到的。(我的就是解壓過程中電腦好像死機了,但是我沒注意,然后沒有解壓完,害的找了半天stdsoap2這個文件)

(二)生成中間文件

在解壓出來的目錄下找到wsdl2h.exe   soapcpp2.exe兩個文件。

2.1 首先生成中間頭文件,作用就是將你的服務端暴露出來的接口生成按網絡格式的函數形式。打開命令行窗口,進入到gsoap目錄下:【我用的C++方式】

wsdl2h  -s  -o   test.h   http://xxxxx:xxxx/xxx.wsdl

wsdl2h常用選項

  • -o 文件名,指定輸出頭文件

  • -n 名空間前綴 代替默認的ns

  • -c 產生純C代碼,否則是C++代碼

  • -s 不要使用STL代碼

  • -t 文件名,指定type map文件,默認為typemap.dat

  • -e 禁止為enum成員加上名空間前綴

后面的***.wsdl是服務端接口說明。如何找到它呢?就我的項目而言,是這樣的:

我的webservice是用c#寫的,直接使用vs2010創(chuàng)建的web工程,【運行該工程】,就會啟動一個web服務了,會彈出瀏覽器打開一個頁面,點擊" *****.asmx ",會看到所有的web接口,然后頁面上有一個“查看說明”字樣的鏈接,點擊應該會進入到 "  ****.wsdl "了,對,就是它。

2.2  根據頭文件生產其他文件

soapcpp2  -j  test.h  

soapcpp2常用選項

  • -C 僅生成客戶端代碼

  • -S 僅生成服務器端代碼

  • -L 不要產生soapClientLib.c和soapServerLib.c文件

  • -c 產生純C代碼,否則是C++代碼(與頭文件有關)

  • -I 指定import路徑(見上文)

  • -x 不要產生XML示例文件

  • -i生成C++包裝,客戶端為xxxxProxy.h(.cpp),服務器端為xxxxService.h(.cpp)。

  • -j 和-i類似,區(qū)別在于生成的代理類不繼承于soap struct,而是包含了一個soap的指針。此種方式生成的代理類便于相互通信

將生成下面這些文件

  • soapStub.h// soap的存根文件,定義了test.h里對應的遠程調用模型

  • soapC.csoapH.h //soap的序列和反序列代碼,它已經包含了soapStub.h,服務器端與客戶端都要包含它

  • soapClient.csoapClientLib.c //C客戶端代碼,soapClientLib.c文件則只是簡單地包含soapClient.c和soapC.c

  • soapServer.csoapServerLib.c //C服務器端代碼,soapServerLib.c文件則只是簡單地包含soapServer.c和soapC.c

  • ServiceSoap.nsmapServiceSoap12.nsmap // 名空間定義,服務器端與客戶端都要包含它

  • soapServiceSoapProxy.hsoapServiceSoap12Proxy.h //客戶端的C++簡單包裝(如果頭文件是純C代碼,這兩個文件就不會生成)

綜上所述

  • 如果編寫服務器端C方式,需要的文件就有:soapStub.h、soapC.cpp  soapH.h  soapServer.c  soapServerLib.c  ServiceSoap.nsmap  ServiceSoap12.nsmap  soapServiceSoapProxy.h  soapServiceSoap12Proxy.h

  • 如果編寫客戶端C++方式,需要的文件就是:soapStub.h  soapC.cpp  soapH.h  soapXXXXSoapProxy.cpp  soapXXXXSoapProxy.h  soapXXXXSoapService.cpp  soapXXXXSoapService.h  XXXXSoap.nsmap

  • 當然,還要加入gsoap庫里的stdsoap2.cpp文件(如果是寫C代碼,則加入stdsoap2.c)【在gsoap根目錄下,不同版本的gsoap對應的該文件是不同的,不可以混用】

  • 到這里test.h已經沒用了

如果看到soapcpp2提示:”Criticalerror: #import: Cannot open file "stlvector.h" forreading.“, 那是因為我們的頭文件使用了STL(wsdl2h沒用-s選項),這時要使用-I選項指定gSOAP的import文件路徑,這個路徑是"$gsoap\gsoap\import":

soapcpp2   -j  test.h -I D:\gsoap-2.7\gsoap\import

(三) 創(chuàng)建代理,入參出參轉換,接收返回值

gsoap會將你的服務端接口進行名字轉換,而且分成請求和響應兩個class(我使用的是C++方式,用起來感覺更簡單一些)。

例如:服務端接口為 int  EncryptPurse(char* cardNum, char*  fileMoney, char* dataOut);

gsoap會將該接口轉換為:

_ns1__EncryptPurse   【請求類,傳遞入參】

_ns1__EncryptPurseResponse 【響應類,獲取出參和返回值】

創(chuàng)建soap結構體和gsoap代理:

struct  soap  soap;

HSM_USCOREEPSaleSoapProxy  soapProxy; // 類型名字會有不同

定義soap的數據傳輸格式:

soap_init(&soap);  //Initializes a runtime context

soap_set_mode(&soap, SOAP_C_MBSTRING); //設置數據模式

soapProxy.HSM_USCOREEPSaleSoapProxy_init(SOAP_C_MBSTRING, SOAP_C_MBSTRING);//初始化數據傳輸模式

然后進行參數轉換,注意入參和出參分別在兩個類中:

_ns1__EncryptPurse    reqEncryptPurse; //創(chuàng)建請求類對象

_ns1__EncryptPurseResponse  respEncryptPurse;  //創(chuàng)建響應類對象

reqEncryptPurse.cardNum = IncardNo;  // IncardNo為實際傳入的參數

reqEncryptPurse.fileMoney = InfileMoney; //InfileMoney為實際傳入的參數

respEncyptPurse.dataOut = Outdata;// Outdata為接收出參的參數

接下來調用接口:

int  ret  = soap.EncryptPurse("http://localhost:1132/EPSaleWebService.asmx", NULL, &reqEncryptPurse, respEncryptPurse);

接收返回值和出參

ret =respResponse.EncryptPurseResult;  //接收EncryptPurse的返回值

strcpy(dataOut, respEncryptPurse.dataOut); //接收出參的值

關閉soap,清理內存:

soap_close(&soap);

soap_end(&soap);

soap_done(&soap);

到這里,一個函數接口的請求和相應就完成了.

遇到的問題:

1.最開始編寫gsoap工程用的vc6,在編譯時報錯:sockaddr_storage未定義的類型

由于winsock的版本不一致導致,改到vs2010里再編譯就沒有該問題了。如果非要在vc6里編譯,請繼續(xù)百度,應該有其他解決方案.

2.error LNK2001: 無法解析的外部符號 _namespaces

  工程--屬性--配置屬性---C/C++---預處理器, 添加 WITH_NONAMESPACES

文章名稱:我的gsoap創(chuàng)建客戶端網絡代理過程
文章起源:http://muchs.cn/article44/jcpehe.html

成都網站建設公司_創(chuàng)新互聯,為您提供網站排名品牌網站制作、自適應網站、響應式網站、網站設計公司、服務器托管

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯

h5響應式網站建設