Ice中间件学习 02 【简单实现HelloWorld】

注:该部分内容部分来自网络。如有侵权请联系

一、简述

创建一个非常easy的客户-serverIce应用,这个应用提供远程地打印功能:client发送要打印的文本给server。再由server把文本发给打印机,打印程序仅仅是把文本打印到终端。而不是真正的打印机,目的是说明客户如何与server通信。

二、安装Ice

Ice官方下载:http://www.zeroc.com/download.html

2.1、安装Ice(过程略)

2.2、配置路径

配置环境变量:将Ice的安装路径下的bin文件夹配置到系统的path环境变量中。例如以下图:

-1

測试安装是否成功。仅仅须要在安装的机器上打开cmd输入slice2java命令就可以(该系列全部文章针对Java语言实现),例如以下图所看到的:

图-2

说明Ice配置完毕!

三、HelloWorld实现

3.1、使用MyEclipse开发,创建一个项目为iceTest的Javaproject,在src

3.2、编写Slice定义

编写不论什么Ice应用的第一个步骤就是要编写一个Slice定义,当中包括应用所用的各个接口。我们为打印应用编写了例如以下这种Slice定义:

module demo{
	interface Printer{
		void printString(string s);
	};
};

我们把这段代码片段保存在叫做printer.ice的文件里,存放在src文件夹下,例如以下图所看到的


-3

Slice定义含有一个接口。叫做Printer,该接口非常easy,仅仅提供了一个操作叫做printString,printString操作接收一个串作为它唯一的输入參数;这个串的文本将会出如今打印机上。

3.3、编写使用Java的Ice应用

3.3.1、编译printer.ice

在cmd命令中进入iceTestproject中printer.ice文件所在的文件夹下,例如以下图所看到的:

-4

cmd中输入命令:slice2java printer.ice

-5

说明:slice2java编译器依据这个printer.ice文件定义生成一些Java源文件,我们眼下无需关注这些文件的确切内容,它们所包括的是编译器生成的代码,与我们在printer.ice中定义的Printer接口相相应。

此时刷新iceTestproject,能够看到多出了非常多的文件,之所以编译以后生成的Java文件存放在demo下,是由于我们的Printer.ice文件里使用module demo定义了包路径。

-6

说明:demo包下的全部Java文件都报错,这是由于没有导入Ice执行所须要的jar包,我们在Ice的安装文件夹下的lib包找到ice.jar,将该jar包导入到iceTestproject下就可以。


图-7

3.3.2、编写和编译server

要实现Printer接口。必须创建一个servant类,依照惯例。servant类的名字是接口的名字加上一个I后缀,所以servant类叫做PrintI,并放在PrinterI.java源文件里,存放在com.xuz.servant包中。

package com.xuz.servant;
import Ice.Current;
import demo._PrinterDisp;
public class PrintI extends _PrinterDisp {
	@Override
	public void printString(String s, Current current) {
		System.out.println(s);
	}
}

说明:PrintI类继承自叫做_PrinterDisp的基类,该类由slice2java编译器生成,是一个抽象类,当中含有一个printString方法。其參数时打印机要打印的串,以及类型为Ice.Current的对象,我们的printString方法的实现会简单地把它的參数写到终端,server代码其余部分在一个叫做Server.java的文件里,存在com.xuz.server包中,以下给出了其完整的代码:

package com.xuz.server;
import com.xuz.servant.PrintI;
public class Server {
	public static void main(String[] args) {
		int status = 0;
		Ice.Communicator ic = null;
		try {
			//初始化连接,args能够传一些初始化參数,如连接超时,初始化client连接池的数量等
			ic = Ice.Util.initialize(args);
			//创建名为SimplePrinterAdapter的适配器。并要求适配器使用缺省的协议(TCP/IP 端口为10000的请求)
			Ice.ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints("SimplePrinterAdapter", "default -p 10000");
			//实例化一个Printer对象,为Printer接口创建一个服务对象
			Ice.Object object = new PrintI();
			//将服务单元添加到适配器中,并给服务对象指定名称为SimplePrinter,该名称用于唯一确定一个服务单元
			adapter.add(object, Ice.Util.stringToIdentity("SimplePrinter"));
			//激活适配器
			adapter.activate();
			//让服务在退出之前。一直持续对请求的监听
			ic.waitForShutdown();
		} catch (Exception e) {
			e.printStackTrace();
			status = 1;
		}finally{
			if(ic!=null){
				ic.destroy();
			}
		}
		System.exit(status);
	}
}

说明:main的主题含有一个try块,把全部的server代码都放在当中。这段代码会在退出之前销毁通信器(假设曾今成功创建过)。要是Ice run time正常结束,这样做是必须的:程序必须调用它所创建的不论什么通信器的destroy;否则就会产生不确定的行为。

我们把对destory的调用放进finally块,这样无论前面的try块中发生什么异常,通信器都保证会正确销毁。

try块中主体含有实际的server代码:

//初始化连接,args能够传一些初始化參数。如连接超时,初始化client连接池的数量等
			ic = Ice.Util.initialize(args);
			//创建名为SimplePrinterAdapter的适配器。并要求适配器使用缺省的协议(TCP/IP 端口为10000的请求)
			Ice.ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints("SimplePrinterAdapter", "default -p 10000");
			//实例化一个Printer对象。为Printer接口创建一个服务对象
			Ice.Object object = new PrintI();
			//将服务单元添加到适配器中。并给服务对象指定名称为SimplePrinter,该名称用于唯一确定一个服务单元
			adapter.add(object, Ice.Util.stringToIdentity("SimplePrinter"));
			//激活适配器
			adapter.activate();
			//让服务在退出之前,一直持续对请求的监听
			ic.waitForShutdown();

这段代码包括了一下步骤:
1)、我们调用Ice.Util.initialize初始化Ice run time(之所以把args传给这个调用。是由于server可能有run time 感兴趣的命令行參数。就这个样例而言,server不须要不论什么命令參数)。对initialize的调用返回的是一个通信器Ice.Communicator引用,这个引用是Ice run time的主句柄。
2)、调用通信Communicator实例上的createObjectAdapterWithEndpoints,创建一个对象适配器,传入的參数是:SimplePrinterAdapter(适配器的名字)。


3)、这时serverrun time已经初始化,实例化一个PrintI对象。为我们的Printer接口创建一个servant。
4)、调用适配器add,告诉它有了一个新的servant。传给add的參数时我们刚才实例化的servant,再加上一个标示符,在这里"SimplePrinter"串是servant的名字(假设有多个打印机。每一个打印机都有不同的名字,更正确的说法是,都会有不同的标示符)。
5)、接下来,调用适配器的activate方法激活适配器(适配器一開始是在holding状态创建。假设适配器处于holding状态。server端run time就会停止从相应的传输端点读取数据,不接受client发送的连接请求,这种做法在以下这种情况下非常实用:假设有非常多歌servant。它们共享同一个适配器。而在全部servant实例化之前我们不想处理请求)。一旦适配器被激活。server就会開始处理来自client的请求。
6)、最后调用waitForShutdown。

这种方法挂起发出调用的线程,直到server实现终止为止-或者是通过发出的一个调用关闭run time,或者是对某个信号做出相应(眼下,当我们不再须要server时,会简单地在命令行上终端它)。
注意:虽然这里的代码不算少,但它们对全部的server都是一样的。你能够把这些代码放在一个辅助类里,然后就无需再为它费心了(Ice提供了一个辅助类:Ice.Application)。就实际的应用代码而言。server仅仅有几行代码:六行代码定义PrintI类,再加上三、四行代码实例化一个PrintI对象。并向对象适配器注冊它。

3.3.3、编写和编译client
client代码在Client.java中,看起来与server非常相似,存放在com.xuz.client包中,代码例如以下:

package com.xuz.client;
import demo.PrinterPrx;
import demo.PrinterPrxHelper;
public class Client {
	public static void main(String[] args) {
		int status = 0;
		Ice.Communicator ic = null;
		try {
			//初始化通信器
			ic = Ice.Util.initialize(args);
			//传入远程服务单元的名称、网络协议、IP以及端口,获取Printer的远程代理,这里使用stringToProxy方式
			Ice.ObjectPrx base = ic.stringToProxy("SimplePrinter:default -p 10000");
			//通过checkedCast向下转型。获取Printer接口的远程。并同一时候检測依据传入的名称获取服务单元是否Printer的代理接口。假设不是则返回null对象
			PrinterPrx printer = PrinterPrxHelper.checkedCast(base);
			if(printer == null){
				throw new Error("Invalid proxy");
			}
			//把Hello world传给服务端。让服务端打印出来,由于这种方法终于会在服务端上执行
			printer.printString("Hello World!");
		} catch (Exception e) {
			e.printStackTrace();
			status = 1;
		}finally{
			if(ic != null){
				ic.destroy();
			}
		}
		System.exit(status);
	}
}

说明:和server一样
1)、调用Ice.initialize初始化Ice run time.
2)、获取远地打印机的代理,调用通信器的stringToProxy创建一个代理,所用參数是:"SimplePrinter:default -p 10000",注意。这个串包括了对象标示符和server所用的端口号一致
3)、stringToProxy返回的代理类型是Ice.ObjectPrx,这种类型位于接口和类的继承树的根部。可是实际与我们的打印机交谈。我们须要的嘶吼Printer接口、而不是Object接口的代理,为此,须要调用PrinterPrxHelper.checkCast进行向下转型。这种方法会发送一条消息给server,实际询问"这是Printer接口的代理吗?",假设是,这个调用就会返回Printer的一个代理,假设代理代表的是其它类型的接口。这个调用就会返回一个空代理。
4)、測试向下转型是否成功。假设不成功,抛出错误消息,终止客户。
5)、如今。在地址空间里面有了一个活的代理,能够调用printerString方法,把hello world串传给它,server会在它的终端上打印出这个串。
3.3.4、执行服务和client
在MyEclipse中,首先执行Server,启动server。再执行Client。在server的Console中我 们会看到打印出了"Hello World!".

四、总结
在本节主要介绍了一个简单的入门级(完整)的client和server的实例。从上可知,编写Ice应用涉及一下几个步骤:
1、编写Slice定义并编译它。
2、编写server并编译它。
3、编写client并编译它。


五、源代码下载:
Ice简单应用源代码下载










          
原文地址:https://www.cnblogs.com/mqxnongmin/p/10959600.html