通过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规范后,我放弃了。。。太复杂了,每个三五个月,是不可能实现的。。。