ICE同步调用与异步调用(3)

7 篇文章 0 订阅

8.1客户端配置

   客户需要执行以下步骤来配置双向连接:
1)创建一个对象适配器接收回调请求。该适配器不需要设置端点,如果它唯一的目的仅仅是在双向连接上接收回调。
2)使用对象适配器注册回调对象。
3)激活对象适配器。
4)代理对象调用ice_getconnection函数,获得连接对象。
5)用获得的连接对象,调用setadapter函数,传递给回调对象适配器。
6)向服务器传递回调对象的身份identity。
   下面C++代码(客户端)说明了这些步骤:

Ice::ObjectAdapterPtr adapter =	communicator >createObjectAdapter("CallbackAdapter");
Ice::Identity ident;
ident.name = IceUtil::generateUUID();
ident.category = "";
adapter >add(new CallbackI, ident);
adapter >activate();
proxy >ice_getConnection() >setAdapter(adapter);
proxy >addClient(ident);

8.2服务器配置

   双向连接实现回调:

1)获得回调对象的身份identity,这个identity通常是由客户端提供的。

2)在连接器上调用函数createproxy,为回调对象创建一个代理。

   这些步骤是在C + +(服务端)代码,如下所示:

void addClient(const Ice::Identity& ident,	const Ice::Current& curr)
{
	CallbackPrx client = CallbackPrx::uncheckedCast(curr.con >createProxy(ident));
	client >notify();
}


 

8.3局限性

双向连接有一定的局限性:
 1)它们只能配置为面向连接的传输,如TCP和SSL。
 2)大多数代理工厂的方法,与一个连接器创建的代理(createproxy)操作是不相关的。
这个代理(createproxy)绑定到一个现有的连接器上,因此代理反映连接的配置。例如,它是不可能去改变这样的代理超时值,否则导致异常FixedProxyException。
 3)双向连接不兼容ACM(Active Connection Management)。

8.4线程的考虑

    ICE运行期间为了处理网络连接通信,通常创建两个线程池:客户端的线程池管理输出(outgoing)连接;服务器的线程池管理输入(incoming)连接。服务器上的所有对象适配器默认共享相同的线程池,但一个对象适配器也可以配置它自己的线程池。客户端和服务器的线程池的大小是1个。
    服务器的线程池通常分配客户端的请求。如果服务器使用一个双向连接发送回调请求,那么服务器线程池还必须处理答复这些请求。
    如果您需要均衡平行多个调度请求的能力,您必须增加适当的线程池大小;或如果您需要进行双向嵌套调用。例如,在一个双向连接上,一个客户端接收回调请求,嵌套调用必须增加客户的线程池大小。详细内容参考ICE嵌套调用的更多信息,并了解在ice上的线程模型细节。

8.6例子

    下面例子演示了如何配置一个双向连接。您可以使用“netstat –an”命令来查看网络连接状态:双向连接只产生一个TCP连接。
    regManager作为会话工厂(sessionFactory),为客户端连接时申请regAgent会话(session)对象。EventHandler作为服务端的回调对象,用来通知客户端。
regManager和regAgent实现过程放在服务器端,EventHandler实现过程放在客户端。
    本章节例子只描述了双向连接过程,其他接口代码未实行。

8.6.1定义接口文件

#ifndef _CLOUDDAQSERVICE_ICE_
#define _CLOUDDAQSERVICE_ICE_

//
// version 1.0.0
//

#include <Ice/Identity.ice>

module CloudDaqService
{
	struct pointStream 
	{
		string pointcode;
		byte   type;
		float  value;
	};

	sequence <pointStream> pointStreamSeq;

	sequence <byte> byteSeq;
	struct eventStream
	{
		byte type;		
		byteSeq value;
	};

	// This exception is raised every time a failure or error is 
	// detected in a treatment.
	exception GeneralException
	{
		string reason;
	};

	interface EventHandler 
	{
		void onNotify(eventStream event);

		// @interface: EventHandler
		// @method   : alive
		// @purpose  : test is the EventHandler is again instantiate and 
		//             so if daq communication part is running
		//             if the call of the method pass, EventHandler is alive; 
		//             else Ice send an exception StateClosed.
		void alive();  
	};

	interface RegAgent
	{
		void hello() throws GeneralException;

		bool write(pointStream data) throws GeneralException;

		bool bulkWrite(pointStreamSeq datum) throws GeneralException;

		pointStreamSeq getPointsValue() throws GeneralException;

		void setEventHandler(EventHandler *handler) throws GeneralException;

		EventHandler *getEventHandler() throws GeneralException;		
	};

	interface RegManager 
	{		
		RegAgent *createInterface(string user, Ice::Identity ident);

		void deleteInterface(string user);
	};
};

#endif

//
// EOF clouddaqservice.ice
//

8.6.2服务端实现代码

1) regmanagerimp.h和regmanagerimp.cpp

#ifndef _REGMANAGERIMP_H
#define _REGMANAGERIMP_H

#include <clouddaqservice.h>
#include <regagentImp.h>

using namespace std;
typedef map<string, RegAgentImp *> RegAgentMap;

class RegManagerImp : public CloudDaqService::RegManager, public IceUtil::Mutex
{
public:

	virtual CloudDaqService::RegAgentPrx createInterface(const string& user, const ::Ice::Identity&, const ::Ice::Current&);
	
	virtual void deleteInterface(const string& user, const ::Ice::Current&);	

public:

	void onNotify(const CloudDaqService::eventStream& event);

	void alive();

	bool checkAgent();

	const int getAgentSize();

private:

	RegAgentMap			RegagentMap_;
};

#endif // _REGMANAGERIMP_H

#include <IceUtil/IceUtil.h>
#include <Ice/Ice.h>
#include <regmanagerimp.h>

CloudDaqService::RegAgentPrx RegManagerImp::createInterface(const string& user, const ::Ice::Identity& ident, const ::Ice::Current& Current)
{
	Lock sync(*this);
	//assert(user != NULL && strlen(user) > 0);

	RegAgentMap::iterator i;
	if ((i = RegagentMap_.find(user)) != RegagentMap_.end())
	{
		const string key = (*i).first;	
		RegAgentImp* pAgent = (*i).second;
		CloudDaqService::RegAgentPrx regAgent = CloudDaqService::RegAgentPrx::uncheckedCast(Current.adapter->addWithUUID(pAgent));
		return regAgent;
	}
	RegAgentImp *pAgent = new RegAgentImp();
	CloudDaqService::RegAgentPrx regAgent;
	regAgent = CloudDaqService::RegAgentPrx::uncheckedCast(Current.con->createProxy(ident));
	RegagentMap_[user] = pAgent;
	return regAgent;	
}

void RegManagerImp::deleteInterface(const string& user, const ::Ice::Current&)
{
	Lock sync(*this);
	//assert(user != NULL);

	RegAgentMap::iterator i;
	for (i = RegagentMap_.begin(); i != RegagentMap_.end(); i++)
	{
		const string key = (*i).first;
		const char *val = (const char *)key.c_str();
		RegAgentImp* pAgent = (*i).second;
		if (strcmp(val, user.c_str()) == 0)
		{
			pAgent->destroy();
			RegagentMap_.erase(i);
			return;
		}
	}
}

void RegManagerImp::onNotify(const CloudDaqService::eventStream& event)
{
	Lock sync(*this);

	RegAgentMap::iterator i;
	if (getAgentSize() <= 0)
	{
		return;
	}

	for (i = RegagentMap_.begin(); i != RegagentMap_.end(); i++)
	{
		const std::string key = (*i).first;
		RegAgentImp* pAgent = (*i).second;
		if (pAgent && !pAgent->checkException())
		{			
			::CloudDaqService::eventStream event;
			event.type = 1;
			pAgent->onNotify(event);
		}
	}
}

void RegManagerImp::alive()
{
	Lock sync(*this);

	RegAgentMap::iterator i;
	if (getAgentSize() <= 0)
	{
		return;
	}

	for (i = RegagentMap_.begin(); i != RegagentMap_.end(); i++)
	{
		const std::string key = (*i).first;
		RegAgentImp* pAgent = (*i).second;
		if (pAgent && !pAgent->checkException())
		{
			pAgent->alive();
		}
	}
}

bool RegManagerImp::checkAgent()
{
	Lock sync(*this);

	bool bRet = false;
	if (getAgentSize() <= 0)
	{
		return bRet;
	}
	RegAgentMap::iterator j = RegagentMap_.begin();
	RegAgentMap::iterator last = RegagentMap_.end();
	while (j != last)
	{
		const std::string key = (*j).first;
		RegAgentImp* pAgent = (*j).second;
		if (pAgent && pAgent->checkException())
		{
			pAgent->destroy();
			RegagentMap_.erase(j);
			bRet = true;
			break;
		}
		++j;
	}
	return bRet;
}

const int RegManagerImp::getAgentSize()
{
	return RegagentMap_.size();
}


2) regagentimp.h和regagentimp.cpp

#ifndef _REGMANAGENTIMP_H
#define _REGMANAGENTIMP_H

#include <clouddaqservice.h>

using namespace std;

class RegAgentImp : public CloudDaqService::RegAgent
{
public:

	RegAgentImp();

	virtual ~RegAgentImp();

public:

	virtual void hello(const ::Ice::Current&);
	
	virtual bool write(const ::CloudDaqService::pointStream&, const ::Ice::Current&);
	
	virtual bool bulkWrite(const ::CloudDaqService::pointStreamSeq&, const ::Ice::Current&);
	
	virtual ::CloudDaqService::pointStreamSeq getPointsValue(const ::Ice::Current&);

	virtual void setEventHandler(const ::CloudDaqService::EventHandlerPrx&, const ::Ice::Current&);

	virtual ::CloudDaqService::EventHandlerPrx getEventHandler(const ::Ice::Current&);

public:

	void onNotify(const ::CloudDaqService::eventStream &event);

	void alive();

	void destroy(void);

	bool checkException(); 

private:

	::CloudDaqService::EventHandlerPrx  Controller_;

	bool		     bException_;

};

#endif // _REGMANAGENTIMP_H

#include <IceUtil/IceUtil.h>
#include <Ice/Ice.h>
#include <regagentimp.h>

RegAgentImp::RegAgentImp()
{
	bException_ = false;
}

RegAgentImp::~RegAgentImp()
{

}

void RegAgentImp::hello(const ::Ice::Current&)
{
	cout << "Hello World!" << endl;
}

bool RegAgentImp::write(const ::CloudDaqService::pointStream&, const ::Ice::Current&)
{
	return true;
}

bool RegAgentImp::bulkWrite(const ::CloudDaqService::pointStreamSeq&, const ::Ice::Current&)
{
	return true;
}

::CloudDaqService::pointStreamSeq RegAgentImp::getPointsValue(const ::Ice::Current&)
{
	::CloudDaqService::pointStreamSeq seq;
	return seq;
}

void RegAgentImp::setEventHandler(const ::CloudDaqService::EventHandlerPrx& eventHander, const ::Ice::Current&)
{
	Controller_ = eventHander;
}

::CloudDaqService::EventHandlerPrx RegAgentImp::getEventHandler(const ::Ice::Current&)
{
	return Controller_;
}

void RegAgentImp::onNotify(const ::CloudDaqService::eventStream &event)
{
	try
	{
		Controller_->onNotify(event);
	}
	catch (const Ice::Exception& ex)
	{
		cerr << ex << endl;
		bException_ = true;
	}
}

void RegAgentImp::alive()
{
	try
	{
		Controller_->alive();
	}
	catch (const Ice::Exception& ex)
	{
		cerr << ex << endl;
		bException_ = true;
	}
}

bool RegAgentImp::checkException()
{
	return bException_;
}

void RegAgentImp::destroy()
{
	
}
3) demoserver.h和demoserver.cpp
#include <ice/ice.h>
#include <regmanagerimp.h>

using namespace std;
using namespace CloudDaqService;

class RefreshTask : public IceUtil::TimerTask
{
public:

	RefreshTask(const Ice::LoggerPtr& logger, RegManagerImp* regManager) :
		_logger(logger), regManager_(regManager)
	{
	}

	virtual void runTimerTask()
	{
		try
		{
			regManager_->alive();
		}
		catch (const Ice::Exception& ex)
		{
			Ice::Warning warn(_logger);
			warn << "RefreshTask: " << ex;
		}
	}

private:

	const Ice::LoggerPtr _logger;
	RegManagerImp   *regManager_;
};

class CloudDaqServer : public Ice::Application
{
public:

	virtual int run(int, char*[]);

private:

	IceUtil::TimerPtr    timer_;
};

int
main(int argc, char* argv[])
{
	CloudDaqServer app;
	return app.main(argc, argv);
}

int
CloudDaqServer::run(int argc, char*[])
{
	Ice::CommunicatorPtr ic = communicator(); 
	Ice::ObjectAdapterPtr adapter = ic->createObjectAdapterWithEndpoints("CloudDaqAdapter", "default -p 10000"); 
	RegManagerImp *pManager = new RegManagerImp;
	CloudDaqService::RegManagerPtr regManager = pManager;
	adapter->add(regManager, communicator()->stringToIdentity("CloudDaq"));
	adapter->activate();

	timer_ = new IceUtil::Timer();
	timer_->scheduleRepeated(new RefreshTask(communicator()->getLogger(), pManager), IceUtil::Time::seconds(5));

	communicator()->waitForShutdown();
	return EXIT_SUCCESS;
}

 

8.6.3客户端实现代码

#include <Ice/Ice.h>
#include <IceUtil/UUID.h>
#include <eventhandlerimp.h>

using namespace std;
using namespace CloudDaqService;

class CloudDaqClient : public Ice::Application
{
public:

	CloudDaqClient();

	virtual int run(int, char*[]);

private:

	void menu();
};

int
main(int argc, char* argv[])
{
	CloudDaqClient app;
	return app.main(argc, argv);
}

//
// Since this is an interactive demo we don't want any signal
// handling.
//
CloudDaqClient::CloudDaqClient() :
    Ice::Application(Ice::NoSignalHandling)
{
}

int
CloudDaqClient::run(int argc, char* argv[])
{
	if (argc > 1)
	{
		cerr << appName() << ": too many arguments" << endl;
		return EXIT_FAILURE;
	}

	Ice::CommunicatorPtr ic = communicator(); 

	Ice::ObjectPrx base = ic->stringToProxy("CloudDaq:default -h 192.168.11.100 -p 10000");
	CloudDaqService::RegManagerPrx regManager =  RegManagerPrx::checkedCast(base); 
	if (!regManager) 
	{
		cerr << argv[0] << ": invalid proxy" << endl;
		return EXIT_FAILURE;
	}

	menu();

	::CloudDaqService::RegAgentPrx regAgent = nullptr;
	char c;
	do
	{
		try
		{
			cout << "==> ";
			cin >> c;
			if (c == 'c' && !regAgent)
			{
				Ice::Identity ident;	
				ident.name = IceUtil::generateUUID();
				ident.category = "";

				Ice::ObjectAdapterPtr adapter = ic->createObjectAdapter("");								
				EventHandlerPtr cb = new EventHandlerImp;
				adapter->add(cb, ident);
				adapter->activate();
				regManager->ice_getConnection()->setAdapter(adapter);

				regAgent = regManager->createInterface("guest", ident);				
			}	
			else if (c == 'h' && regAgent)
			{
				regAgent->hello();
			}
			else if (c == 'x')
			{
				// Nothing to do
			}
			else if(c == '?')
			{ 
				menu();
			}
			else
			{
				cout << "unknown command `" << c << "'" << endl;
				menu();
			}
		}
		catch (const Ice::Exception& ex)
		{
			cerr << ex << endl;
		}
	}
	while (cin.good() && c != 'x');

	return EXIT_SUCCESS;
}

void
CloudDaqClient::menu()
{
	cout <<
		"usage:\n"
		"c: create agent interface by user\n"
		"h: send hello to server\n"
		"x: exit\n"
		"?: help\n";
}

 

9 总结

    本文主要简单介绍了几种常见的函数调用方法,并以一些已经测试通过的例子来说明各种调用方法。其中可能需要关注的是回调函数、双向连接和异步调用(AMI和AMD)使用情况。因ICE牵涉的内容很多,具体细节见官方网站完整说明。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值