最近學習了異步通信這一章:異步包括服務端的異步分派(AMD)以及客戶端的異步調用(AMI)。
下面介紹一下如何實現簡單的異步通信(主要實現了客戶端的異步調用,AMD暫未體現):
1.首先編寫Ice文件:Demo.ice
- module Demo{
- interface Employee{
- ["amd"]void add(int a, int b, out int sum);
- };
- };
["amd"]表示的是元數據,指定服務器端將提供異步分派的方法函數。該add函數中有兩個in參數;一個out參數,作爲回傳參數。
2.映射到C++代碼:使用命令 slice2cpp Demo.ice
經過映射之後,程序將生成Demo.h與Demo.cpp文件,如下面部分代碼所示Demo.h
- // ....More code before
- namespace Demo
- {
- class Employee : virtual public ::Ice::Object
- {
- public:
- typedef EmployeePrx ProxyType;
- typedef EmployeePtr PointerType;
- virtual ::Ice::ObjectPtr ice_clone() const;
- virtual bool ice_isA(const ::std::string&, const ::Ice::Current& = ::Ice::Current()) const;
- virtual ::std::vector< ::std::string> ice_ids(const ::Ice::Current& = ::Ice::Current()) const;
- virtual const ::std::string& ice_id(const ::Ice::Current& = ::Ice::Current()) const;
- static const ::std::string& ice_staticId();
- virtual void add_async(const ::Demo::AMD_Employee_addPtr&, ::Ice::Int, ::Ice::Int, const ::Ice::Current& = ::Ice::Current()) = 0;
- // ... More code here
- };
- // ...
3. 實現服務端程序
新建Server.cpp文件,將Demo.h中的虛方法add_async()實現。並新建servant類來繼承Ice::application類,初始化Ice run time ,同時將servant註冊到對象適配器中去。
- #include <Demo.h>
- #include <Ice/Application.h>
- #include <IceUtil/Monitor.h>
- #include <iostream>
- using namespace std;
- using namespace Demo;
- class Manager : virtual public Employee,public IceUtil::Monitor<IceUtil::Mutex>
- {
- public:
- Manager():_sum(0){}
- ~Manager(){}
- virtual void add_async(const ::Demo::AMD_Employee_addPtr& add_ptr, int a, int b, const ::Ice::Current& =::Ice::Current())
- {
- _sum = a+b;
- sleep(1);
- cout<< "The sum is " <<_sum<<"."<<endl;
- add_ptr->ice_response(_sum); //數據處理完之後,回調函數,調用客戶端實現的方法
- }
- private:
- int _sum;
- };
- class myApplication : virtual public Ice::Application
- {
- public:
- virtual int run(int argc , char* argv[])
- {
- Ice::ObjectAdapterPtr adapter =
- communicator()->createObjectAdapterWithEndpoints("GameServer", "default -p 10000");
- Ice::ObjectPtr Manptr = new Manager;
- adapter->add(Manptr, communicator()->stringToIdentity("ManServer"));//將servant類對象指針ManPtr註冊到適配器中
- adapter->activate(); //激活適配器,使客戶端能夠訪問適配器中已添加的servant活動表
- communicator()->waitForShutdown();
- }
- };
- int main(int argc , char * argv[])
- {
- myApplication app;
- app.main(argc , argv);
- return 0;
- }
4.實現客戶端程序
新建Client.cpp文件,實現回調函數,創建訪問指定servant的代理。
- #include<Ice/Ice.h>
- #include<Demo.h>
- #include<iostream>
- #include<IceUtil/IceUtil.h>using namespace std;
- using namespace Demo;class Client_add:public AMD_Employee_add
- {
- public:
- virtual void ice_response(int sum)
- {
- cout << "receive from server--The sum is "<<sum<<"."<<endl;
- }
- virtual void ice_exception(){}
- virtual void ice_exception(const std::exception& e){}
- void failed_operation(const Ice::Exception &e){}
- };
- typedef IceUtil::Handle<Client_add> ClientAddPtr;class ClientApp : virtual public Ice::Application
- {
- public:
- virtual int run(int argc , char* argv[])
- {
- Ice::ObjectPrx base = communicator()->stringToProxy("ManServer:default -p 10000"); EmployeePrx emp = EmployeePrx::checkedCast(base); if(!emp)throw "Invalid Proxy!"; ClientAddPtr amd_add = new Client_add;
- Callback_Employee_addPtr addPtr=newCallback_Employee_add(amd_add,&Client_add::ice_response,&Client_add::failed_operation); //實現回調對象指針
- emp->begin_add(10,20,addPtr); //第三個參數爲回調類的智能指針 cout<<"I'm waiting for the data from,but not blocked."<<endl; }
- };int main(int argc , char* argv[])
- {
- ClientApp app;
- app.main(argc , argv); return 0;
- }
5. 編譯Server.cpp: g++ Demo.cpp Server.cpp -o Server -lIce -lIceUtil -I./ -I/opt/Ice-3.4.2/include -L/opt/Ice-3.4.2/lib
編譯Client.cpp: g++ Demo.cpp Client.cpp -o Client -lIce -lIceUtil -I./ -I/opt/Ice-3.4.2/include -L/opt/Ice-3.4.2/lib
運行服務端:./Server 運行客戶端:./Client