双向连接(Bidirectional Connections)
ICE的连接通常允许请求只在一个方向流动。如果一个应用程序的设计需要服务器会回调到客户端,服务器通常建立新的连接(如4章节的回调函数)。
图8.1 callback
不幸的是当我们在网络限制条件下,服务器与客户端之间,往往只允许创建一个单独的连接。如图5.2所示,当客户端位于防火墙后面。
图8.2 与防火墙的回调函数。
在两个双向连接流的方向上提供可能要求,以客户端用户现有的连接,使服务器发送到客户端回调请求。
定义一个接口Callback.ice:
- #pragma once
- #include <Ice/Identity.ice>
- module Demo
-
- {
- interface CallbackReceiver
- {
- void callback(int num);
- };
- interface CallbackSender
- {
- void addClient(Ice::Identity ident);
- };
- };
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);
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();
- }
3局限性
双向连接有一定的局限性:
1)它们只能配置为面向连接的传输,如TCP和SSL。
2)大多数代理工厂的方法,与一个连接器创建的代理(createproxy)操作是不相关的。
这个代理(createproxy)绑定到一个现有的连接器上,因此代理反映连接的配置。例如,它是不可能去改变这样的代理超时值,否则导致异常FixedProxyException。
3)双向连接不兼容ACM(Active Connection Management)。
4线程的考虑
ICE运行期间为了处理网络连接通信,通常创建两个线程池:客户端的线程池管理输出(outgoing)连接;服务器的线程池管理输入(incoming)连接。服务器上的所有对象适配器默认共享相同的线程池,但一个对象适配器也可以配置它自己的线程池。客户端和服务器的线程池的大小是1个。
服务器的线程池通常分配客户端的请求。如果服务器使用一个双向连接发送回调请求,那么服务器线程池还必须处理答复这些请求。
如果您需要均衡平行多个调度请求的能力,您必须增加适当的线程池大小;或如果您需要进行双向嵌套调用。例如,在一个双向连接上,一个客户端接收回调请求,嵌套调用必须增加客户的线程池大小。详细内容参考ICE嵌套调用的更多信息,并了解在ice上的线程模型细节。
5例子
下面例子演示了如何配置一个双向连接。您可以使用“netstat –an”命令来查看网络连接状态:双向连接只产生一个TCP连接。
regManager作为会话工厂(sessionFactory),为客户端连接时申请regAgent会话(session)对象。EventHandler作为服务端的回调对象,用来通知客户端。
regManager和regAgent实现过程放在服务器端,EventHandler实现过程放在客户端。
本章节例子只描述了双向连接过程,其他接口代码未实行。
1定义接口文件
- #ifndef _CLOUDDAQSERVICE_ICE_
- #define _CLOUDDAQSERVICE_ICE_
-
-
-
-
-
- #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;
- };
-
-
-
- exception GeneralException
- {
- string reason;
- };
-
- interface EventHandler
- {
- void onNotify(eventStream event);
-
-
-
-
-
-
-
- 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
-
-
-
-
8.6.2服务端实现代码
1) regmanagerimp.h和regmanagerimp.cpp
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客户端实现代码
9 总结
本文主要简单介绍了几种常见的函数调用方法,并以一些已经测试通过的例子来说明各种调用方法。其中可能需要关注的是回调函数、双向连接和异步调用(AMI和AMD)使用情况。因ICE牵涉的内容很多,具体细节见官方网站完整说明。
转自:http://blog.csdn.net/liuxuezong/article/details/28950287
双向连接(Bidirectional Connections)
ICE的连接通常允许请求只在一个方向流动。如果一个应用程序的设计需要服务器会回调到客户端,服务器通常建立新的连接(如4章节的回调函数)。
图8.1 callback
不幸的是当我们在网络限制条件下,服务器与客户端之间,往往只允许创建一个单独的连接。如图5.2所示,当客户端位于防火墙后面。
图8.2 与防火墙的回调函数。
在两个双向连接流的方向上提供可能要求,以客户端用户现有的连接,使服务器发送到客户端回调请求。
定义一个接口Callback.ice:
- #pragma once
-
- #include <Ice/Identity.ice>
-
- module Demo
-
- {
- interface CallbackReceiver
- {
- void callback(int num);
- };
- interface CallbackSender
- {
- void addClient(Ice::Identity ident);
- };
- };
0 0