6.2 ICE 双向连接

来源:互联网 发布:辽宁2016经济数据 编辑:程序博客网 时间:2024/05/29 08:37

双向连接(Bidirectional Connections)

        ICE的连接通常允许请求只在一个方向流动。如果一个应用程序的设计需要服务器会回调到客户端,服务器通常建立新的连接(如4章节的回调函数)。

图8.1 callback

        不幸的是当我们在网络限制条件下,服务器与客户端之间,往往只允许创建一个单独的连接。如图5.2所示,当客户端位于防火墙后面。

图8.2 与防火墙的回调函数。

          在两个双向连接流的方向上提供可能要求,以客户端用户现有的连接,使服务器发送到客户端回调请求。

          定义一个接口Callback.ice:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #pragma once  
  2. #include <Ice/Identity.ice>  
  3. module Demo  
  4.   
  5. {  
  6.     interface CallbackReceiver  
  7.     {  
  8.         void callback(int num);  
  9.     };  
  10.     interface CallbackSender  
  11.     {  
  12.         void addClient(Ice::Identity ident);  
  13.     };  
  14. };  


1客户端配置

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

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. Ice::ObjectAdapterPtr adapter = communicator >createObjectAdapter("CallbackAdapter");  
  2. Ice::Identity ident;  
  3. ident.name = IceUtil::generateUUID();  
  4. ident.category = "";  
  5. adapter >add(new CallbackI, ident);  
  6. adapter >activate();  
  7. proxy >ice_getConnection() >setAdapter(adapter);  
  8. proxy >addClient(ident);  

2服务器配置

 双向连接实现回调:

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

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

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

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. void addClient(const Ice::Identity& ident,  const Ice::Current& curr)  
  2. {  
  3.     CallbackPrx client = CallbackPrx::uncheckedCast(curr.con >createProxy(ident));  
  4.     client >notify();  
  5. }  


 

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定义接口文件

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #ifndef _CLOUDDAQSERVICE_ICE_  
  2. #define _CLOUDDAQSERVICE_ICE_  
  3.   
  4. //  
  5. // version 1.0.0  
  6. //  
  7.   
  8. #include <Ice/Identity.ice>  
  9.   
  10. module CloudDaqService  
  11. {  
  12.     struct pointStream   
  13.     {  
  14.         string pointcode;  
  15.         byte   type;  
  16.         float  value;  
  17.     };  
  18.   
  19.     sequence <pointStream> pointStreamSeq;  
  20.   
  21.     sequence <byte> byteSeq;  
  22.     struct eventStream  
  23.     {  
  24.         byte type;        
  25.         byteSeq value;  
  26.     };  
  27.   
  28.     // This exception is raised every time a failure or error is   
  29.     // detected in a treatment.  
  30.     exception GeneralException  
  31.     {  
  32.         string reason;  
  33.     };  
  34.   
  35.     interface EventHandler   
  36.     {  
  37.         void onNotify(eventStream event);  
  38.   
  39.         // @interface: EventHandler  
  40.         // @method   : alive  
  41.         // @purpose  : test is the EventHandler is again instantiate and   
  42.         //             so if daq communication part is running  
  43.         //             if the call of the method pass, EventHandler is alive;   
  44.         //             else Ice send an exception StateClosed.  
  45.         void alive();    
  46.     };  
  47.   
  48.     interface RegAgent  
  49.     {  
  50.         void hello() throws GeneralException;  
  51.   
  52.         bool write(pointStream data) throws GeneralException;  
  53.   
  54.         bool bulkWrite(pointStreamSeq datum) throws GeneralException;  
  55.   
  56.         pointStreamSeq getPointsValue() throws GeneralException;  
  57.   
  58.         void setEventHandler(EventHandler *handler) throws GeneralException;  
  59.   
  60.         EventHandler *getEventHandler() throws GeneralException;          
  61.     };  
  62.   
  63.     interface RegManager   
  64.     {         
  65.         RegAgent *createInterface(string user, Ice::Identity ident);  
  66.   
  67.         void deleteInterface(string user);  
  68.     };  
  69. };  
  70.   
  71. #endif  
  72.   
  73. //  
  74. // EOF clouddaqservice.ice  
  75. //  

8.6.2服务端实现代码

1) regmanagerimp.h和regmanagerimp.cpp

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #ifndef _REGMANAGERIMP_H  
  2. #define _REGMANAGERIMP_H  
  3.   
  4. #include <clouddaqservice.h>  
  5. #include <regagentImp.h>  
  6.   
  7. using namespace std;  
  8. typedef map<string, RegAgentImp *> RegAgentMap;  
  9.   
  10. class RegManagerImp : public CloudDaqService::RegManager, public IceUtil::Mutex  
  11. {  
  12. public:  
  13.   
  14.     virtual CloudDaqService::RegAgentPrx createInterface(const string& user, const ::Ice::Identity&, const ::Ice::Current&);  
  15.       
  16.     virtual void deleteInterface(const string& user, const ::Ice::Current&);      
  17.   
  18. public:  
  19.   
  20.     void onNotify(const CloudDaqService::eventStream& event);  
  21.   
  22.     void alive();  
  23.   
  24.     bool checkAgent();  
  25.   
  26.     const int getAgentSize();  
  27.   
  28. private:  
  29.   
  30.     RegAgentMap         RegagentMap_;  
  31. };  
  32.   
  33. #endif // _REGMANAGERIMP_H  
  34.   
  35. #include <IceUtil/IceUtil.h>  
  36. #include <Ice/Ice.h>  
  37. #include <regmanagerimp.h>  
  38.   
  39. CloudDaqService::RegAgentPrx RegManagerImp::createInterface(const string& user, const ::Ice::Identity& ident, const ::Ice::Current& Current)  
  40. {  
  41.     Lock sync(*this);  
  42.     //assert(user != NULL && strlen(user) > 0);  
  43.   
  44.     RegAgentMap::iterator i;  
  45.     if ((i = RegagentMap_.find(user)) != RegagentMap_.end())  
  46.     {  
  47.         const string key = (*i).first;    
  48.         RegAgentImp* pAgent = (*i).second;  
  49.         CloudDaqService::RegAgentPrx regAgent = CloudDaqService::RegAgentPrx::uncheckedCast(Current.adapter->addWithUUID(pAgent));  
  50.         return regAgent;  
  51.     }  
  52.     RegAgentImp *pAgent = new RegAgentImp();  
  53.     CloudDaqService::RegAgentPrx regAgent;  
  54.     regAgent = CloudDaqService::RegAgentPrx::uncheckedCast(Current.con->createProxy(ident));  
  55.     RegagentMap_[user] = pAgent;  
  56.     return regAgent;      
  57. }  
  58.   
  59. void RegManagerImp::deleteInterface(const string& user, const ::Ice::Current&)  
  60. {  
  61.     Lock sync(*this);  
  62.     //assert(user != NULL);  
  63.   
  64.     RegAgentMap::iterator i;  
  65.     for (i = RegagentMap_.begin(); i != RegagentMap_.end(); i++)  
  66.     {  
  67.         const string key = (*i).first;  
  68.         const char *val = (const char *)key.c_str();  
  69.         RegAgentImp* pAgent = (*i).second;  
  70.         if (strcmp(val, user.c_str()) == 0)  
  71.         {  
  72.             pAgent->destroy();  
  73.             RegagentMap_.erase(i);  
  74.             return;  
  75.         }  
  76.     }  
  77. }  
  78.   
  79. void RegManagerImp::onNotify(const CloudDaqService::eventStream& event)  
  80. {  
  81.     Lock sync(*this);  
  82.   
  83.     RegAgentMap::iterator i;  
  84.     if (getAgentSize() <= 0)  
  85.     {  
  86.         return;  
  87.     }  
  88.   
  89.     for (i = RegagentMap_.begin(); i != RegagentMap_.end(); i++)  
  90.     {  
  91.         const std::string key = (*i).first;  
  92.         RegAgentImp* pAgent = (*i).second;  
  93.         if (pAgent && !pAgent->checkException())  
  94.         {             
  95.             ::CloudDaqService::eventStream event;  
  96.             event.type = 1;  
  97.             pAgent->onNotify(event);  
  98.         }  
  99.     }  
  100. }  
  101.   
  102. void RegManagerImp::alive()  
  103. {  
  104.     Lock sync(*this);  
  105.   
  106.     RegAgentMap::iterator i;  
  107.     if (getAgentSize() <= 0)  
  108.     {  
  109.         return;  
  110.     }  
  111.   
  112.     for (i = RegagentMap_.begin(); i != RegagentMap_.end(); i++)  
  113.     {  
  114.         const std::string key = (*i).first;  
  115.         RegAgentImp* pAgent = (*i).second;  
  116.         if (pAgent && !pAgent->checkException())  
  117.         {  
  118.             pAgent->alive();  
  119.         }  
  120.     }  
  121. }  
  122.   
  123. bool RegManagerImp::checkAgent()  
  124. {  
  125.     Lock sync(*this);  
  126.   
  127.     bool bRet = false;  
  128.     if (getAgentSize() <= 0)  
  129.     {  
  130.         return bRet;  
  131.     }  
  132.     RegAgentMap::iterator j = RegagentMap_.begin();  
  133.     RegAgentMap::iterator last = RegagentMap_.end();  
  134.     while (j != last)  
  135.     {  
  136.         const std::string key = (*j).first;  
  137.         RegAgentImp* pAgent = (*j).second;  
  138.         if (pAgent && pAgent->checkException())  
  139.         {  
  140.             pAgent->destroy();  
  141.             RegagentMap_.erase(j);  
  142.             bRet = true;  
  143.             break;  
  144.         }  
  145.         ++j;  
  146.     }  
  147.     return bRet;  
  148. }  
  149.   
  150. const int RegManagerImp::getAgentSize()  
  151. {  
  152.     return RegagentMap_.size();  
  153. }  


2) regagentimp.h和regagentimp.cpp

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #ifndef _REGMANAGENTIMP_H  
  2. #define _REGMANAGENTIMP_H  
  3.   
  4. #include <clouddaqservice.h>  
  5.   
  6. using namespace std;  
  7.   
  8. class RegAgentImp : public CloudDaqService::RegAgent  
  9. {  
  10. public:  
  11.   
  12.     RegAgentImp();  
  13.   
  14.     virtual ~RegAgentImp();  
  15.   
  16. public:  
  17.   
  18.     virtual void hello(const ::Ice::Current&);  
  19.       
  20.     virtual bool write(const ::CloudDaqService::pointStream&, const ::Ice::Current&);  
  21.       
  22.     virtual bool bulkWrite(const ::CloudDaqService::pointStreamSeq&, const ::Ice::Current&);  
  23.       
  24.     virtual ::CloudDaqService::pointStreamSeq getPointsValue(const ::Ice::Current&);  
  25.   
  26.     virtual void setEventHandler(const ::CloudDaqService::EventHandlerPrx&, const ::Ice::Current&);  
  27.   
  28.     virtual ::CloudDaqService::EventHandlerPrx getEventHandler(const ::Ice::Current&);  
  29.   
  30. public:  
  31.   
  32.     void onNotify(const ::CloudDaqService::eventStream &event);  
  33.   
  34.     void alive();  
  35.   
  36.     void destroy(void);  
  37.   
  38.     bool checkException();   
  39.   
  40. private:  
  41.   
  42.     ::CloudDaqService::EventHandlerPrx  Controller_;  
  43.   
  44.     bool             bException_;  
  45.   
  46. };  
  47.   
  48. #endif // _REGMANAGENTIMP_H  
  49.   
  50. #include <IceUtil/IceUtil.h>  
  51. #include <Ice/Ice.h>  
  52. #include <regagentimp.h>  
  53.   
  54. RegAgentImp::RegAgentImp()  
  55. {  
  56.     bException_ = false;  
  57. }  
  58.   
  59. RegAgentImp::~RegAgentImp()  
  60. {  
  61.   
  62. }  
  63.   
  64. void RegAgentImp::hello(const ::Ice::Current&)  
  65. {  
  66.     cout << "Hello World!" << endl;  
  67. }  
  68.   
  69. bool RegAgentImp::write(const ::CloudDaqService::pointStream&, const ::Ice::Current&)  
  70. {  
  71.     return true;  
  72. }  
  73.   
  74. bool RegAgentImp::bulkWrite(const ::CloudDaqService::pointStreamSeq&, const ::Ice::Current&)  
  75. {  
  76.     return true;  
  77. }  
  78.   
  79. ::CloudDaqService::pointStreamSeq RegAgentImp::getPointsValue(const ::Ice::Current&)  
  80. {  
  81.     ::CloudDaqService::pointStreamSeq seq;  
  82.     return seq;  
  83. }  
  84.   
  85. void RegAgentImp::setEventHandler(const ::CloudDaqService::EventHandlerPrx& eventHander, const ::Ice::Current&)  
  86. {  
  87.     Controller_ = eventHander;  
  88. }  
  89.   
  90. ::CloudDaqService::EventHandlerPrx RegAgentImp::getEventHandler(const ::Ice::Current&)  
  91. {  
  92.     return Controller_;  
  93. }  
  94.   
  95. void RegAgentImp::onNotify(const ::CloudDaqService::eventStream &event)  
  96. {  
  97.     try  
  98.     {  
  99.         Controller_->onNotify(event);  
  100.     }  
  101.     catch (const Ice::Exception& ex)  
  102.     {  
  103.         cerr << ex << endl;  
  104.         bException_ = true;  
  105.     }  
  106. }  
  107.   
  108. void RegAgentImp::alive()  
  109. {  
  110.     try  
  111.     {  
  112.         Controller_->alive();  
  113.     }  
  114.     catch (const Ice::Exception& ex)  
  115.     {  
  116.         cerr << ex << endl;  
  117.         bException_ = true;  
  118.     }  
  119. }  
  120.   
  121. bool RegAgentImp::checkException()  
  122. {  
  123.     return bException_;  
  124. }  
  125.   
  126. void RegAgentImp::destroy()  
  127. {  
  128.       
  129. }  
  130. 3) demoserver.h和demoserver.cpp  
  131. #include <ice/ice.h>  
  132. #include <regmanagerimp.h>  
  133.   
  134. using namespace std;  
  135. using namespace CloudDaqService;  
  136.   
  137. class RefreshTask : public IceUtil::TimerTask  
  138. {  
  139. public:  
  140.   
  141.     RefreshTask(const Ice::LoggerPtr& logger, RegManagerImp* regManager) :  
  142.         _logger(logger), regManager_(regManager)  
  143.     {  
  144.     }  
  145.   
  146.     virtual void runTimerTask()  
  147.     {  
  148.         try  
  149.         {  
  150.             regManager_->alive();  
  151.         }  
  152.         catch (const Ice::Exception& ex)  
  153.         {  
  154.             Ice::Warning warn(_logger);  
  155.             warn << "RefreshTask: " << ex;  
  156.         }  
  157.     }  
  158.   
  159. private:  
  160.   
  161.     const Ice::LoggerPtr _logger;  
  162.     RegManagerImp   *regManager_;  
  163. };  
  164.   
  165. class CloudDaqServer : public Ice::Application  
  166. {  
  167. public:  
  168.   
  169.     virtual int run(intchar*[]);  
  170.   
  171. private:  
  172.   
  173.     IceUtil::TimerPtr    timer_;  
  174. };  
  175.   
  176. int  
  177. main(int argc, char* argv[])  
  178. {  
  179.     CloudDaqServer app;  
  180.     return app.main(argc, argv);  
  181. }  
  182.   
  183. int  
  184. CloudDaqServer::run(int argc, char*[])  
  185. {  
  186.     Ice::CommunicatorPtr ic = communicator();   
  187.     Ice::ObjectAdapterPtr adapter = ic->createObjectAdapterWithEndpoints("CloudDaqAdapter""default -p 10000");   
  188.     RegManagerImp *pManager = new RegManagerImp;  
  189.     CloudDaqService::RegManagerPtr regManager = pManager;  
  190.     adapter->add(regManager, communicator()->stringToIdentity("CloudDaq"));  
  191.     adapter->activate();  
  192.   
  193.     timer_ = new IceUtil::Timer();  
  194.     timer_->scheduleRepeated(new RefreshTask(communicator()->getLogger(), pManager), IceUtil::Time::seconds(5));  
  195.   
  196.     communicator()->waitForShutdown();  
  197.     return EXIT_SUCCESS;  
  198. }  

 

8.6.3客户端实现代码

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include <Ice/Ice.h>  
  2. #include <IceUtil/UUID.h>  
  3. #include <eventhandlerimp.h>  
  4.   
  5. using namespace std;  
  6. using namespace CloudDaqService;  
  7.   
  8. class CloudDaqClient : public Ice::Application  
  9. {  
  10. public:  
  11.   
  12.     CloudDaqClient();  
  13.   
  14.     virtual int run(intchar*[]);  
  15.   
  16. private:  
  17.   
  18.     void menu();  
  19. };  
  20.   
  21. int  
  22. main(int argc, char* argv[])  
  23. {  
  24.     CloudDaqClient app;  
  25.     return app.main(argc, argv);  
  26. }  
  27.   
  28. //  
  29. // Since this is an interactive demo we don't want any signal  
  30. // handling.  
  31. //  
  32. CloudDaqClient::CloudDaqClient() :  
  33.     Ice::Application(Ice::NoSignalHandling)  
  34. {  
  35. }  
  36.   
  37. int  
  38. CloudDaqClient::run(int argc, char* argv[])  
  39. {  
  40.     if (argc > 1)  
  41.     {  
  42.         cerr << appName() << ": too many arguments" << endl;  
  43.         return EXIT_FAILURE;  
  44.     }  
  45.   
  46.     Ice::CommunicatorPtr ic = communicator();   
  47.   
  48.     Ice::ObjectPrx base = ic->stringToProxy("CloudDaq:default -h 192.168.11.100 -p 10000");  
  49.     CloudDaqService::RegManagerPrx regManager =  RegManagerPrx::checkedCast(base);   
  50.     if (!regManager)   
  51.     {  
  52.         cerr << argv[0] << ": invalid proxy" << endl;  
  53.         return EXIT_FAILURE;  
  54.     }  
  55.   
  56.     menu();  
  57.   
  58.     ::CloudDaqService::RegAgentPrx regAgent = nullptr;  
  59.     char c;  
  60.     do  
  61.     {  
  62.         try  
  63.         {  
  64.             cout << "==> ";  
  65.             cin >> c;  
  66.             if (c == 'c' && !regAgent)  
  67.             {  
  68.                 Ice::Identity ident;      
  69.                 ident.name = IceUtil::generateUUID();  
  70.                 ident.category = "";  
  71.   
  72.                 Ice::ObjectAdapterPtr adapter = ic->createObjectAdapter("");                               
  73.                 EventHandlerPtr cb = new EventHandlerImp;  
  74.                 adapter->add(cb, ident);  
  75.                 adapter->activate();  
  76.                 regManager->ice_getConnection()->setAdapter(adapter);  
  77.   
  78.                 regAgent = regManager->createInterface("guest", ident);                
  79.             }     
  80.             else if (c == 'h' && regAgent)  
  81.             {  
  82.                 regAgent->hello();  
  83.             }  
  84.             else if (c == 'x')  
  85.             {  
  86.                 // Nothing to do  
  87.             }  
  88.             else if(c == '?')  
  89.             {   
  90.                 menu();  
  91.             }  
  92.             else  
  93.             {  
  94.                 cout << "unknown command `" << c << "'" << endl;  
  95.                 menu();  
  96.             }  
  97.         }  
  98.         catch (const Ice::Exception& ex)  
  99.         {  
  100.             cerr << ex << endl;  
  101.         }  
  102.     }  
  103.     while (cin.good() && c != 'x');  
  104.   
  105.     return EXIT_SUCCESS;  
  106. }  
  107.   
  108. void  
  109. CloudDaqClient::menu()  
  110. {  
  111.     cout <<  
  112.         "usage:\n"  
  113.         "c: create agent interface by user\n"  
  114.         "h: send hello to server\n"  
  115.         "x: exit\n"  
  116.         "?: help\n";  
  117. }  

 

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:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #pragma once  
  2.   
  3. #include <Ice/Identity.ice>  
  4.   
  5. module Demo  
  6.   
  7. {  
  8.     interface CallbackReceiver  
  9.     {  
  10.         void callback(int num);  
  11.     };  
  12.     interface CallbackSender  
  13.     {  
  14.         void addClient(Ice::Identity ident);  
  15.     };  
  16. };  
0 0
原创粉丝点击