Ubuntu16.04下ZeroC ICE的安装与使用示例,Qt C++ 和 Java

项目需求:在Ubuntu16.04系统下安装并使用ICEgrid 3.7进行c++和Java Springboot开发环境的通信,下面逐一介绍各个步骤的详解:

一:Ice Lib的安装

参考官网地址:https://doc.zeroc.com/ice/latest/release-notes/using-the-linux-binary-distributions#id-.UsingtheLinuxBinaryDistributionsv3.7-InstallingIceonUbuntu

首先添加Key和仓库地址:

1 sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv B6391CB2CFBA643D
2 sudo apt-add-repository -s "deb http://zeroc.com/download/Ice/3.7/ubuntu`lsb_release -rs` stable main"

更新软件包并安装:

1 sudo apt-get update
2 sudo apt-get install zeroc-ice-all-runtime zeroc-ice-all-dev

安装时可能会提示amd386的相关错误,忽视就行。如提示有缺失试试以下命令:

sudo apt-get upgrade -f

可以通过查看ice版本和slice版本的方法查看是否安装成功:

icegridNode -v

slice2cpp -v

二:Maven项目添加Ice依赖包

在pom.xml中添加如下依赖即可:

 1 <repository>
 2             <id>ice</id>
 3             <name>ice Nexus Repository</name>
 4             <url>https://repo.zeroc.com/nexus/content/repositories/releases/</url>
 5 </repository>    
 6 
 7 <dependency>
 8             <groupId>com.zeroc</groupId>
 9             <artifactId>ice</artifactId>
10             <version>3.7.2</version>
11 </dependency>

三:ice文件示例编写与切片

编写helloworld.ice:

1 module Demo {
2     interface Printer 
3     {
4         void printString(string s);
5     };
6 };

分别用slice2cpp生成C++代码,用slice2java生成java代码

四:QT ice项目构建与编写

qmake.pro文件添加如下依赖:

LIBS += -L/usr/lib\

-lIce\

并将上一步生成的helloworld.cpp和helloworld.h放入项目中

用c++编写简单的服务端:

 1 #include <QCoreApplication>
 2 #include <Ice/Ice.h>
 3 #include <helloworld.h>
 4 
 5 using namespace std;
 6 using namespace Demo;
 7 
 8 // 从Printer抽象类派生
 9 class PrinterI : public Printer {
10 public:
11     //ICE接口方法中都会自动增加一个参数 Ice::Current,不过在这个HelloWorld程序中我们不需要用到
12     virtual void printString(const string& s, const Ice::Current&){
13         cout << s << endl;
14     }
15 };
16 
17 int main(int argc, char** argv)
18 {
19     int status = 0;  //退出状态
20     //ic是一个指向ICE运行时资源的智能指针,通过ic可以获取运行时的各种资源。
21     Ice::CommunicatorPtr ic;
22     try {
23     //  Ice::initialize 初始化一个ICE运行时。传入 argc,argv是因为服务代码可能会处理命令行参数(本例中不需要)。
24     ic = Ice::initialize(argc, argv);
25     // 创建一个 ObjectAdapterPtr adapter,名字为 SimplePrinterAdapter。这个Adapter监听TCP/IP的10000端口
26     Ice::ObjectAdapterPtr adapter =
27     ic->createObjectAdapterWithEndpoints("HelloIce:default","tcp -p 10000");
28 
29     // 实例化一个PrinterI对象,该对象将为接口Printer提供服务
30     Ice::ObjectPtr object = new PrinterI;
31 
32     // 把PrinterI对象加入ObjectAdapter,标识名为SimplePrinter。当有客户端请求Printer的服务时,ObjectAdapter将会把请求转给PrinterI对象
33     adapter->add(object, ic->stringToIdentity("HelloIce"));
34 
35     // 启动ObjectAdapter, 此后ObjectAdapter开始处理实际的调用请求
36     adapter->activate();
37 
38     // 阻塞主线程,直到服务端的运行时被关闭
39     ic->waitForShutdown();
40 
41     } catch (const Ice::Exception& e) {
42         cerr << e << endl;
43         status = 1;
44     } catch (const char* msg) {
45         cerr << msg << endl;
46         status = 1;
47     }
48 
49     // 程序结束时,需要销毁ICE运行时资源。如果在程序退出时没有对ICE运行时进行销毁,可能引起未知错误
50     if (ic)
51     {
52         try {
53         ic->destroy();
54         } catch (const Ice::Exception& e) {
55         cerr << e << endl;
56         status = 1;
57         }
58     }
59     return status;
60 }

客户端:

 1 #include <QCoreApplication>
 2 #include <Ice/Ice.h>
 3 #include <helloworld.h>
 4 
 5 using namespace std;
 6 using namespace Demo;
 7 
 8 int main(int argc, char** argv)
 9 {
10     Ice::CommunicatorPtr ic = Ice::initialize(argc, argv);
11     Ice::ObjectPrx proxy = ic->stringToProxy("HelloIce:default -p 10000");
12     PrinterPrx printer = PrinterPrx::checkedCast(proxy);
13     printer->printString("Hello Server");
14     ic->destroy();
15     cout << "End Client" << endl;
16     return 0;
17 }

五:Java代码编写

接口实现类:

 1 package com.demo.test.IceTest;
 2 
 3 import com.zeroc.Ice.Current;
 4 
 5 public class PrinterI implements Printer{
 6 
 7     public void printString(String s, Current __current){
 8         System.out.println(s);
 9     }
10 
11 }

服务器类:

 1 package com.demo.test.IceTest;
 2 
 3 import com.zeroc.Ice.Communicator;
 4 import com.zeroc.Ice.ObjectAdapter;
 5 import com.zeroc.Ice.Object;
 6 import com.zeroc.Ice.Util;
 7 
 8 public class IceTestServer {
 9 
10     public static void main(String[] args){
11         try(Communicator communicator = Util.initialize(args)) {
12             ObjectAdapter adapter = communicator.createObjectAdapterWithEndpoints("HelloIce:default", "default -p 10000");
13             Object obj = new PrinterI();
14             adapter.add(obj, Util.stringToIdentity("HelloIce"));
15             adapter.activate();
16             communicator.waitForShutdown();
17         }
18     }
19 
20 }

客户端类:

 1 //Ice接口测试,客户端
 2 package com.demo.test.IceTest;
 3 
 4 import com.zeroc.Ice.Communicator;
 5 import com.zeroc.Ice.ObjectPrx;
 6 import com.zeroc.Ice.Util;
 7 
 8 public class IceTestClient {
 9 
10     public static void main(String[] args){
11         System.out.println("Client Start");
12         Communicator ic = null;
13         ic = Util.initialize();
14         ObjectPrx proxy = ic.stringToProxy("HelloIce:default -p 10000");
15         PrinterPrx printer = PrinterPrx.checkedCast(proxy);
16         printer.printString("Hello server");
17         ic.destroy();
18         System.out.println("Client Destroy");
19     }
20 }

常见问题:

1.本文所用ice版本是3.7.2,所生成的java文件有3个:_PrinterPrxl.java,  Printer.java,  PrinterPrx.java,若ice版本不同生成文件可能也不同,编程规范也不同

2.在Linux系统下若使用小于1024的端口号会提示权限错误,出现该错误改端口号即可。