1、ICE是什么?
ICE是ZEROC的开源通信协议产品,它的全称是:The Internet Communications Engine,翻译为中文是互联网通信引擎,是一个面向对象的中间件,它封装并实现了底层的通讯逻辑,使我们能够方便的构建分布式应用程序。相对于只面向WINDOWS系统微软的.NET(以及原来的DCOM)、复杂的CORBA及性能较差的WEB SERVICE等分布式方案,ICE很好的解决了这些中间件的不足:它支持不同的系统,如WINDOWS、LINUX等,支持在多种开发语言上使用,如C++、C、JAVA、RUBY、PYTHON、VB等。服务端可以是上面提到的任何一种语言实现的,客户端也可以根据自己的实际情况选择不同的语言实现,如服务端采用C语言实现,而客户端采用JAVA语言实现等。
2: ICE的安装和示例
2.1 ICE安装
ICE官网:https://zeroc.com,点击download后选择合适的平台/开发环境即可,Ubuntu18.04的安装如下图。
notes: 注意ICE3.7.2与3.6.x版本差异较大,头文件不互相兼容,选用时需注意客户端/服务端ICE版本的一致性,避免代码无法编译通过。
2.2: hello world代码示例
官网的helloworld程序,详见官网目录https://doc.zeroc.com/ice/3.7/hello-world-application
首先创建一个slice文件Printer.ice
,并将程序需要远程调用的接口写入其中。对于hello world程序,slice文件可按如下来写:
module Demo { interface Printer { void printString(string s); } }
下面我们以C++(c++11)为例,分别实现服务端和客户端。首先,我们使用slice2cpp将ice文件转换成C++可使用的.h和.cpp文件。其中.h文件中包含了我们需要远程调用的接口定义以及ICE封装,最主要的有Printer和PrinterPrx类,分别是服务端需要实现的具体对象和客户端使用的代理,其中PrinterPrx代理类中还提供了printStringAsync异步调用方法。
slice2cpp Printer.ice
服务端需要实现Printer类的接口,并创建本地创建,之后添加到ice适配器上,以便客户端远程调用。具体实现代码如下:
#include <Ice/Ice.h> #include <Printer.h> using namespace std; using namespace Demo; class PrinterI : public Printer { public: virtual void printString(string s, const Ice::Current&) override; }; void PrinterI::printString(string s, const Ice::Current&) { cout << s << endl; } int main(int argc, char* argv[]) { try { Ice::CommunicatorHolder ich(argc, argv); auto adapter = ich->createObjectAdapterWithEndpoints("SimplePrinterAdapter", "default -h localhost -p 10000"); auto servant = make_shared<PrinterI>(); adapter->add(servant, Ice::stringToIdentity("SimplePrinter")); adapter->activate(); ich->waitForShutdown(); } catch(const std::exception& e) { cerr << e.what() << endl; return 1; } return 0; }
客户端需要创建远程对象的代理,并通过代理进行远程调用,代码如下:
#include <Ice/Ice.h> #include <Printer.h> #include <stdexcept> using namespace std; using namespace Demo; int main(int argc, char* argv[]) { try { Ice::CommunicatorHolder ich(argc, argv); auto base = ich->stringToProxy("SimplePrinter:default -p 10000"); auto printer = Ice::checkedCast<PrinterPrx>(base); if(!printer) { throw std::runtime_error("Invalid proxy"); } printer->printString("Hello World!"); } catch(const std::exception& e) { cerr << e.what() << endl; return 1; } return 0; }
上面的demo演示了ice远程调用的基本工作方式,ICE接口的详细解释既可通过ICE官网查看,也可在安装ICE后查看相应的头文件注释。然而实际工程中我们需要对ice进行配置,处理网络异常,在服务端进行回调,穿透防火墙,进行线程调度等工作。虽然在ICE的chat demo中有介绍这些工作