ICE远程函数调用
用ICE框架可以很容易地实现远程函数调用,广泛使用在分布式系统中。
ICE框架由客户端和服务器组成,支持客户端并发地调用服务器的服务。默认是一个同步调用。可以改成异步调用。
?
下面给出一个简单的例子。实现客户端和服务器间的一问一答。
?
服务器部分:
?
服务器做的工作稍微多点,首先我们需要定义一个ice文件,包含我们需要的接口。
?IM.ice
#ifndef IM_ICE#define IM_ICEmodule 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
?