通過GSOAP自帶的wsdl2h和soap2cpp可以生成基于C++語言的服務端代碼Service和客戶端代碼Proxy,這樣調用起來就很方便了。對于Service來說,只要將其放到一個線程中,等待客戶端連接并相應請求就可以了;而對于客戶端,直接調用Proxy對象的方法就可以向服務端發送請求了。
??? 好用是好用,但如果Service很多的話,每個都寫一次線程封裝,這太可怕了,而一個線程帶動全部Service由不現實,這時,C++模版的威力就體現出來了~看如下代碼實例:
#ifndef?__SOAPSERVICETASKTEMPLATE_H__
#define?__SOAPSERVICETASKTEMPLATE_H__
#include?<string>
#include?<iostream>
#include?"acex/ACEX.h"
#include?"acex/Task.h"
#include?"stdsoap2.h"
template<typename?T>
class?CSoapServiceObject?:?public?T
{
public:
public:
????CSoapServiceObject()?{}
????virtual?~CSoapServiceObject()?{}
????int?Init(const?std::string&?strAddr);
????void?Shutdown()?{?_bStop?=?true;?}
public:
????virtual?int?svc();
private:
????bool?_bStop;
????std::string?_strHost;
????unsigned?short?_usPort;
};
template<typename?T>
int?CSoapServiceObject<T>::Init(const?std::string?&strAddr)
{
????std::string::size_type?pos?=?strAddr.find(":");
????if(pos?!=?std::string::npos)
????{
????????_strHost?=?strAddr.substr(pos?+?1);
????????_usPort?=?ACE_OS::atoi(_strHost.c_str());
????????_strHost?=?strAddr.substr(0,?pos);
????}
????else
????{
????????_usPort?=?ACE_OS::atoi(strAddr.c_str());
????}
????return?0;
}
template<typename?T>
int?CSoapServiceObject<T>::svc()
{
????if(_strHost.empty())
????{
????????if(!soap_valid_socket(this->bind(NULL,?_usPort,?100)))
????????????return?this->error;
????}
????else
????{
????????if(!soap_valid_socket(this->bind(_strHost.c_str(),?_usPort,?100)))
????????????return?this->error;
????}
????while(!_bStop)
????{
????????if(!soap_valid_socket(this->accept()))
????????????return?this->error;
????????this->serve();
????????soap_destroy(this);
????????soap_end(this);
????}
????return?0;
}
//////////////////////////////////////////////////////////////////////////
template<typename?T>
class?CSoapServiceTask?:?public?ACEX_Synch_Task
{
public:
????CSoapServiceTask()?{}
????virtual?~CSoapServiceTask()?{}
????int?Init(const?std::string&?strAddr);
????void?Shutdown();
protected:
????virtual?int?svc();
private:
????T?_objService;
};
template<typename?T>
int?CSoapServiceTask<T>::Init(const?std::string&?strAddr)
{
????return?_objService.Init(strAddr);
}
template<typename?T>
void?CSoapServiceTask<T>::Shutdown()
{
????_objService.Shutdown();
}
template<typename?T>
int?CSoapServiceTask<T>::svc()
{
????return?_objService.svc();
}
#endif
??? 以上是對Service的封裝,使用時,只要用如下語句即可:
if(Service.Init(strAddr)?==?0)
{
??Service.activate();
}
??? 下面是一個使用實例:
#include?"SoapServiceTaskTemplate.h"
#include?"soapSmsNotificationBindingService.h"
class?CSoapNotifyServiceObject?:?public?CSoapServiceObject<SmsNotificationBindingService>
{
public:
????CSoapNotifyServiceObject();
????virtual?~CSoapNotifyServiceObject();
public:
????virtual????int?notifySmsReception(isag5__notifySmsReception?*isag5__notifySmsReception_,?isag5__notifySmsReceptionResponse?*isag5__notifySmsReceptionResponse_);
????virtual????int?notifySmsDeliveryReceipt(isag5__notifySmsDeliveryReceipt?*isag5__notifySmsDeliveryReceipt_,?isag5__notifySmsDeliveryReceiptResponse?*isag5__notifySmsDeliveryReceiptResponse_);
};
typedef?CSoapServiceTask<CSoapNotifyServiceObject>?TSoapNotifyServiceTask;
typedef?ACE_Singleton<TSoapNotifyServiceTask,?ACE_Recursive_Thread_Mutex>?TSoapNotifyServiceTask_Singleton;
#define?SoapNotifyServiceTask?TSoapNotifyServiceTask_Singleton::instance()
??? 使用如上方法,只需編寫Service相應的函數即可,大大減少編寫重復代碼的時間,爽了~
??? 例子中使用的一個基類
ACEX_Synch_Task,是基于ACE封裝的線程類,功能和其它線程類類似,svc()函數為線程處理部分函數。WebService使用的是一個通訊行業的接口規范,不復雜,就是Service多的要命~
??? GSOAP使用的感覺就是--厲害但不好用。。。。。可能是我對WebService規范和GSOAP不熟悉所致,反正用起來很不順手,比如Service請求不能異步應答,對于通訊消息處理代碼寫多的我來說,這個很不習慣,當然也許是GSOAP支持,是我不會用。。。
??? GSOAP不好用,弄得我都想自己寫個基于C++的WebService庫來,但簡單看了SOAP規范后,我放棄了。。。太復雜了,每個三五個月,是不可能實現的。。。