用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