Codejie's C++ Space

Using C++

GSOAP:使用模版封装Serivce线程

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

posted on 2009-07-03 18:20 codejie 阅读(1722) 评论(2)  编辑 收藏 引用 所属分类: C++

评论

# re: GSOAP:使用模版封装Serivce线程 2009-08-10 09:21 uwinb

soap_bind() 和 soap_accept() 等都定义在stdsoap2.cpp文件中
只有soap_serve()定义在soapServer.cpp文件中,与具体接口相关
所以即使不用模板这把利剑,通过函数指针也可以很好地封装代码

另一方面如果把多个wsdl文件合并后再生成代码,(当然我不会合并啦)
所有的接口不就能共用同一个服务器了  回复  更多评论   

# re: GSOAP:使用模版封装Serivce线程 2009-08-10 10:57 codejie

嗯,模版我只是用到很习惯,函数指针,我一直认为有点偏C,所以用的很少,也许按你的思路作会再简单些~

多个WSDL合并,GSOAP是支持的,而且也蛮好用的;但是--我要用到的多个WSDL文件比较‘笨蛋’,其内部定义的类型和调用在不同的文件中存在同名问题,这个搞死我了~  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

Using C++

导航

统计

留言簿(73)

随笔分类(513)

积分与排名

最新评论

阅读排行榜

评论排行榜