gsoap 使用方法

C/C++ 想使用 WebService ,那麼非常好的一個選擇就是 gsoap ,本文檔針對 gsoap 的入門,對深入的層面不進行過多的探討,關於 WebService 的概念和 gsoap 高級應用,會另外有文檔涉及。

gsoap 在網上的資料比較少,我猜想可能的原因是 gsoap 在應用中大多使用 Java 或者 .net ,而 C/C++ 使用的比較少。多餘的話就不贅述了。現在開始。

gsoap 下載: SourceForge.net

下載後,在 Linux Windows 下的安裝使用就不多贅述了。只要有一點關於開源軟件的使用經驗就足夠了。

gsoap 主要的應用程序分爲兩個: wsdl2h soapcpp2

wsdl2h 是將 wsdl 定義轉換成 .h 文件的工具。主要有一些選項:

-c 代表轉化成 C 代碼。

-s 代表不使用 STL ,取而代之需要在工程中包含 stdsoap2.h stdsoap2.cpp 。這些在安裝的源碼中都可以找到。

-o file 代表指定輸出文件名稱。

通常情況下使用命令 wsdl2h –s xxx.wsdl 即可生成想要的 .h 文件。

 

soapcpp2 是生成源碼的工具,從某種意義上來說, WebService ICE 相當的相像。都是網絡通信協議的封裝方式,所不同的是 WebService 使用的是公開協議。沒有特殊選項的情況下 ,gsoap 不需要依賴其他的鏈接庫。 soapcpp2 的主要選項有:

-S 代表生成客戶端代碼。

-C 代表生成服務端代碼。

-L 代表不生成 soapClientLib/soapServerLib

-c 代表僅生成 c 代碼

-i 代表使用 Proxy

通常情況下使用命令 soapcpp2 –S/-C –L -i xxx.h

 

在編寫客戶端的時候,比較簡單,分成兩種方式:使用 Proxy 的方式相對來說,比較簡單 ,Demo 源碼如下:

#include <iostream>

#include "soapcurrentTimeProxy.h"

#include "currentTime.nsmap"

using namespace std;

int main() {

        cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!

        currentTimeProxy currentTime;

        int nRet=0;

         if(currentTime.currentTime(10,&nRet) == SOAP_OK)

                printf("Return %d/n",nRet);

        else

                currentTime.soap_stream_fault(std::cerr);

        return 0;

}

有幾個地方需要注意:

1.       需要包含 XXX.nsmap 文件,這非常重要,這是表示 WebService 的語義所在。

2.       這個 Demo 是使用 Proxy 的調用方式,即在 soapcpp2 使用了 -i 這個參數。

3.       如果使用了 wsdl2h –s 參數,需要包含 stdsoap2.h stdsoap2.cpp

4.       請不要包含 soapClientLib/soapServerLib

Client 端使用非 Proxy 的方式省略,這在網上到處都是,需要關注的點差不多。另外關於 WebService 訪問地址的問題。在正常情況下, WebService 地址在 wsdl 中指定。但除了這種方式,還可以使用指定 Server ip port 的方式,在 soap 有個成員變量 endpoint ,填寫這個參數就可以。

編成服務端的情況稍微多一點,之所以這樣說,可以把 WebService 的服務端分成兩種調用方式:一種是使用 gsoap 來做 Http Server ;另外一種使用 httpd 或者其他的東西來做 HttpServer ,而 gsoap 作爲 cgi

Demo 如下:

#include "soaptest2PortBindingObject.h"

#include "test2PortBinding.nsmap"

#include <iostream>

 

using namespace std;

int main() {

         cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!

        struct soap soap;

        int m, s; // master and slave sockets

        soap_init(&soap);

        m = soap_bind(&soap, "10.130.15.133", 80, 100);

        if (m < 0)

                 soap_print_fault(&soap, stderr);

        else

        {

                fprintf(stderr, "Socket connection successful: master socket = %d/n", m);

                for (int i = 1; ; i++)

                {

                        s = soap_accept(&soap);

                        if (s < 0)

                        {

                                soap_print_fault(&soap, stderr);

                                break;

                       }

                        fprintf(stderr, "%d: accepted connection from IP=%d.%d.%d.%d socket=%d/n", i,(soap.ip>>24)&0xFF, (soap.ip>>16)&0xFF, (soap.ip>>8)&0xFF, soap.ip&0xFF, s);

                        if (soap_serve(&soap) != SOAP_OK) // process RPC request

                                soap_print_fault(&soap, stderr); // print error

                        fprintf(stderr, "request served/n");

                        soap_destroy(&soap); // clean up class instances

                        soap_end(&soap); // clean up everything and close socket

                }

         }    

        return 0;

}       

Client 不同的是,這裏沒有使用 Proxy 方式,這裏省略了兩個需要實現的接口函數。從接口調用來分析 Bind 是啓動 httpServer 的端口監聽。而 accept 是接受 WebService 請求。 Serve 是提供 WebService 服務。這是使用 gsoap 自己作爲 httpServer ,這個程序起來的時候,就會在循環中不斷接受請求,然後提供服務,也就是說這個程序是一直啓動的,並在循環中提供服務。這個一個單線程的程序,也就是說,同時只能處理一個請求,在效率上不是最佳的。那麼有兩種方式可以處理,一是使用多線程來調用 Serve ;二是使用 httpd 來作爲 httpServer 。下面就是這樣一個 Demo:

int main()

{

// create soap context and serve one CGI-based request:

        soap_serve(soap_new());

}

非常簡單,一次調用就執行一次程序。相當於使用多進程來處理併發請求。而調度器是 httpd 。將這個程序放在 httpd cgi 空間中就可以了。

最後的提示,不要輕易定義什麼編譯宏。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章