前一階段寫gSOAP 的文章沒保存好,後來想寫的,越學越沒有寫的勇氣了,感覺自己很菜,但是現在感覺還是寫點就算給入門者一點提示吧。另外雖說這篇文章是自己寫的,但是卻感覺是東拼西湊的,有很多別人的東西了。
看了我轉載的關於soap 的文章,大家想必對soap有所瞭解了吧,那麼gSOAP是什麼那? gSOAP 是一個開源的項目,用它可以方便的使用c/c++地進行SOAP客戶端和服務器端編程,而不必瞭解xml和SOAP協議的細節。這樣使用者就可以專注於自 己的web service 客戶端或服務器端的編寫,而不用糾纏與其它細節。我第一次接觸這些東西,我對SOAP的理解是這樣的:以http協議爲基本的通信協議,以xml文件形式 請求遠程服務,再以xml文件的形式返回執行結果,我理解的就這麼簡單了,有啥不妥處,還請指教阿。 實踐一下才有理性認識,下面是我自己在windows下,具體說來就是用vc 6.0下編寫的一個很簡單的客戶端程序調用遠程的服務,來發送電子郵件,感覺很爽吧。 首先我們到 http://sourceforge.net/project/showfiles.php?group_id=52781 下載gSOAP下載工具集吧,不同的系統下用的gSOAP是不一樣的,根據需要下載了windows下的和linux下的。 gSOAP工具集不需要安裝,直接解壓就可以了。在/bin目錄下我們可以看到兩個可執行文件: soapcpp2.exe: gSOAP編譯器,編譯頭文件生成服務器和客戶端都需要的 c/c++文件。 wsdl2h.exe: 編譯wsdl文件生成c/c++頭文件。 工具就算準備好了。 其次,我們到 http://www.abysal.com/soap/AbysalEmail.wsdl 下載 wsdl文件,假設保存文件名爲:AbysalEmail.wsdl。所謂的wsdl文件翻譯成中 文就是網絡服務描述文件了。我們用wsdl2h.exe工具來根據wsdl文件生成 c/c++頭文件,可以用-c選項是生成純c的頭文件,另外用-s選項是說明我們在 程序中不使用stl,注意了默認我們是適用stl的。 用如下命令: wsdl2h --t ../typemap.dat -o AbysalEmail.h AbysalEmail.wsdl 既可以生成我們需要的AbysalEmail.h頭文件了。這裏文件名可以隨便起了。 將下載的gsoap的import裏的stlvector.h中文件拷貝到當前的文件夾下,因爲默認是使用stl的,所以需要它。 然後執行soapcpp2 命令來生成存根程序,用如下命令: soapcpp2 -C AbysalEmail.h -C 選項是隻生成客戶端的,默認是生成客戶端和服務器端的,如果你在程序中使用了vector還要加上 –limport選項。 即可以生存客戶端存根程序和框架了。 soapClient.cpp:編譯客戶端的需要的存根例程。 soapC.cpp,soapH.h:用來序列化和反序列化c/c++不同數據類型。 soapServer.cpp: 編譯服務器端的需要的存根例程。 soapXXXProxy.h: 生成的代理類的頭文件,使用代理類時需要此文件。 本程序爲soapSendEmailBindingProxy.h。 第三步,就是在vc中建個工程,設置如下: 在vc6中建立工程,其源文件爲:sendMailClient.cpp soapC.cpp soapClient.cpp stdsoap2.cpp 頭文件爲: AbysalEmail.h soapH.h soapStub.h stdsoap2.h 其他依賴文件爲:basetsd.h sendemailbinding.nsmp stdsoap2.cpp stdsoap2.h是下載的gSOAP中包含的。 另外在所需要的庫中把wsock32.lib加上,gSOAP也是採用socket方式連接的。 其中sendMailClient.cpp爲我寫的客戶端程序,程序如下: #include "soapH.h" // 得到存根程序 #include "SendEmailBinding.nsmap" //得到名稱空間映射表 #include <iostream> #include <string> #include "soapSendEmailBindingProxy.h" using namespace std; int main(int argc, char **argv) { struct soap email_soap; int result = -1; SendEmailBinding EmailBind; //生成代理類對象 _ns1__SendEmail sendEmail; //web服務發送電子郵件對象 _ns1__SendEmailResponse Email_Response; //web 服務返回發送結果對象 string from = "mseaspring"; string to = "David"; string sub = "Hello test!"; sendEmail.From = &from; sendEmail.FromAddress = " [email protected] "; sendEmail.MsgBody = "I want to test a web service!"; sendEmail.To = &to; sendEmail.ToAddress = " [email protected] "; sendEmail.Subject = ⊂ result = EmailBind.__ns1__SendEmail(&sendEmail, &Email_Response); if (result != 0) { printf("soap error ,errcode = %d/n", result); } else { cout<<"The result is :"<<Email_Response.ReturnCode<<endl; cout<<"恭喜你,郵件發送成功!"<<endl; } return 0; }我程序中是採用代理類的方式編寫的程序,不用代理類的代碼如下: #include "soapH.h" // 得到存根程序 #include "SendEmailBinding.nsmap" // 得到名稱空間映射表 #include <iostream> #include <string> using namespace std; int main(int argc, char **argv) { struct soap email_soap; //初始化gSoap運行時環境變量,只需初始化一次 soap_init(&email_soap); int result = -1; //遠程web服務的endpoint URL const char* server="http://www.abysal.com/soap/soapmail.wdtp"; string from = "mseaspring"; string to = "David"; string sub = "Hello test!"; sendEmail.From = &from; sendEmail.FromAddress = " [email protected] "; sendEmail.MsgBody = "I want to test a web service!"; sendEmail.To = &to; sendEmail.ToAddress = " [email protected] "; sendEmail.Subject = ⊂ //調用根據遠程服務產生函數的接口 result = soap_call___ns1__SendEmail(&email_soap, server, "", &sendEmail, &Email_Response); if(email_soap.error) { //在stderr流中打印soap的錯誤信息 soap_print_fault(&email_soap,stderr); result = email_soap.error; } soap_destroy(&email_soap);// 刪除反序列化類的實例,僅用於c++ soap_end(&email_soap); // 清空已經並行化的數據 soap_done(&email_soap); // 與gSOAP 環境相分離,關閉連接 if (result != 0) { printf("soap error ,errcode = %d/n", result); } else { cout<<"The result is :"<<Email_Response.ReturnCode<<endl; cout<<"恭喜你,郵件發送成功!"<<endl; } return 0; } 你可能會問我怎麼知道遠程服務的接口阿? 到soapStub.h中去找就可以了,至於代理類的使用,到代理類頭文件中一看便知。 好了,終於要寫完了,當然我們不僅可以編寫客戶端也可以編寫服務器端程序,至於服務器端,有興趣的可以自己看看gSOAP裏面的文檔,也很簡單的,不過也要花點時間學習的了,呵呵。 如果對於上面程序,有誰沒調試成功聯繫我,郵箱都寫在程序裏那。呵呵。 |