用ICE框架可以很容易地实现远程函数调用,广泛使用在分布式系统中。
ICE框架由客户端和服务器组成,支持客户端并发地调用服务器的服务。默认是一个同步调用。可以改成异步调用。
下面给出一个简单的例子。实现客户端和服务器间的一问一答。
服务器部分:
服务器做的工作稍微多点,首先我们需要定义一个ice文件,包含我们需要的接口。
IM.ice
#ifndef IM_ICE #define IM_ICE module IM { interface IMInterface { int SendMsg( string req, out string rsp); }; }; #endif
然后使用slice2cpp这个bin生成IM.h和IM.cpp,
slice2cpp IM.ice
自己写一个类IMInterfaceI继承IMInterface,并实现SendMsg这个方法。
SendMsg在IMInterface中是一个纯虚函数,必须在IMInterfaceI中实现。
IMInterfaceI.h
#ifndef __IM_INTERFACE_I_H__ #define __IM_INTERFACE_I_H__ #include "IM.h" using namespace IM; class IMInterfaceI : public IMInterface { ::Ice::Int SendMsg(const ::std::string&, ::std::string&, const ::Ice::Current& = ::Ice::Current()); }; #endif
IMInterfaceI.cpp
#include "IMInterfaceI.h" #include <iostream> using namespace std; ::Ice::Int IMInterfaceI::SendMsg(const ::std::string& req, ::std::string& rsp, const ::Ice::Current&) { cout << req << endl; getline(cin, rsp); return 0; }
这样我们就可以启动这个服务了,让客户端来调用SendMsg这个接口。
Server.cpp
#include <Ice/Ice.h> #include "IMInterfaceI.h" using namespace std; int main(int argc, char** argv) { int status = 0; Ice::CommunicatorPtr ic; try { ic = Ice::initialize(argc, argv); Ice::ObjectAdapterPtr adapter = ic->createObjectAdapterWithEndpoints("IM", "default -p 9999"); //IMInterfaceI是由ice文件生成的类派生出来的 Ice::ObjectPtr object = new IMInterfaceI(); //"IMInterface"是我们这个实例的标志符 //以后提供给客户端的连接串就是"IMInterface:default -p 9999" //default = tcp -h 127.0.0.1,可以显式表达 adapter->add(object, ic->stringToIdentity("IMInterface")); adapter->activate(); ic->waitForShutdown(); } catch (const Ice::Exception& e) { cerr << e << endl; status = 1; } catch (const char* msg) { cerr << msg << endl; status = 1; } if (ic) { try { ic->destroy(); } catch (const Ice::Exception& e) { cerr << e << endl; status = 1; } } return status; }
最后编译连接,这个服务就可以用了。
c++ -I. -I$ICE_HOME/include -c IM.cpp IMInterfaceI.cpp Server.cpp
echo ".o generated successfully!\n"
c++ -o Server IM.o IMInterfaceI.o Server.o -L$ICE_HOME/lib -lIce -lIceUtil
echo ".o linked successfully!\n"
客户端部分:
将Server的ice文件拷过来,用slice2cpp这个bin生成IM.h和IM.cpp
然后就可以调用了。
#include "IM.h" #include <Ice/Ice.h> #include <iostream> #include <cstring> using namespace std; using namespace IM; int main(int argc, char** argv) { int status = 0; Ice::CommunicatorPtr ic; try { ic = Ice::initialize(argc, argv); //"IMInterface:default -p 9999"是服务器提供的连接串 Ice::ObjectPrx base = ic->stringToProxy("IMInterface:default -p 9999"); IMInterfacePrx ptr = IMInterfacePrx::checkedCast(base); if (!ptr) throw "Invalid proxy"; string req, rsp; while (getline(cin, req)) { ptr->SendMsg(req, rsp); cout << rsp << endl; } } catch (const Ice::Exception& ex) { cerr << ex << endl; status = 1; } catch (const char* msg) { cerr << msg << endl; status = 1; } if (ic) ic->destroy(); return status; }
客户端的编译生成可执行文件的脚本。从脚本可以清晰地看到3个步骤。
1.slice2cpp生成一些.h,.cpp文件
2.编译出.o文件
3.连接.o文件形成可执行文件Client
ICE_HOME=/opt/ICE
slice2cpp IM.ice
c++ -I. -I$ICE_HOME/include -c IM.cpp Client.cpp
c++ -o Client IM.o Client.o -L$ICE_HOME/lib -lIce -lIceUtil