溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

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

發(fā)布時(shí)間:2020-07-15 09:15:53 來源:網(wǎng)絡(luò) 閱讀:778 作者:pq4362050 欄目:建站服務(wù)器

2017年06月11日16:42:58

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

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

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

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

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

(二)生成中間文件

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

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

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

wsdl2h常用選項(xiàng)

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

  • -n 名空間前綴 代替默認(rèn)的ns

  • -c 產(chǎn)生純C代碼,否則是C++代碼

  • -s 不要使用STL代碼

  • -t 文件名,指定type map文件,默認(rèn)為typemap.dat

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

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

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

2.2  根據(jù)頭文件生產(chǎn)其他文件

soapcpp2  -j  test.h  

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)。

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

將生成下面這些文件

  • soapStub.h// soap的存根文件,定義了test.h里對(duì)應(yīng)的遠(yuǎn)程調(diào)用模型

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

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

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

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

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

綜上所述

  • 如果編寫服務(wù)器端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

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

  • 到這里test.h已經(jīng)沒用了

如果看到soapcpp2提示:”Criticalerror: #import: Cannot open file "stlvector.h" forreading.“, 那是因?yàn)槲覀兊念^文件使用了STL(wsdl2h沒用-s選項(xiàng)),這時(shí)要使用-I選項(xiàng)指定gSOAP的import文件路徑,這個(gè)路徑是"$gsoap\gsoap\import":

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

(三) 創(chuàng)建代理,入?yún)⒊鰠⑥D(zhuǎn)換,接收返回值

gsoap會(huì)將你的服務(wù)端接口進(jìn)行名字轉(zhuǎn)換,而且分成請(qǐng)求和響應(yīng)兩個(gè)class(我使用的是C++方式,用起來感覺更簡單一些)。

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

gsoap會(huì)將該接口轉(zhuǎn)換為:

_ns1__EncryptPurse   【請(qǐng)求類,傳遞入?yún)ⅰ?/span>

_ns1__EncryptPurseResponse 【響應(yīng)類,獲取出參和返回值】

創(chuàng)建soap結(jié)構(gòu)體和gsoap代理:

struct  soap  soap;

HSM_USCOREEPSaleSoapProxy  soapProxy; // 類型名字會(huì)有不同

定義soap的數(shù)據(jù)傳輸格式:

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

soap_set_mode(&soap, SOAP_C_MBSTRING); //設(shè)置數(shù)據(jù)模式

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

然后進(jìn)行參數(shù)轉(zhuǎn)換,注意入?yún)⒑统鰠⒎謩e在兩個(gè)類中:

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

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

reqEncryptPurse.cardNum = IncardNo;  // IncardNo為實(shí)際傳入的參數(shù)

reqEncryptPurse.fileMoney = InfileMoney; //InfileMoney為實(shí)際傳入的參數(shù)

respEncyptPurse.dataOut = Outdata;// Outdata為接收出參的參數(shù)

接下來調(diào)用接口:

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

接收返回值和出參

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

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

關(guān)閉soap,清理內(nèi)存:

soap_close(&soap);

soap_end(&soap);

soap_done(&soap);

到這里,一個(gè)函數(shù)接口的請(qǐng)求和相應(yīng)就完成了.


遇到的問題:

1.最開始編寫gsoap工程用的vc6,在編譯時(shí)報(bào)錯(cuò): sockaddr_storage未定義的類型

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

2. error LNK2001: 無法解析的外部符號(hào) _namespaces

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


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI