The Ice Programming Model
ICE编程包含4步:
1. 用Slice(Specification Languagefor Ice)定义类型和接口。
2. 将Slice定义(Slice definitions)编译为你选择的语言。
3. 写客户端, 其中使用到Slice编译器生成的代码
4. 写服务器,其中使用到Slice编译器生成的代码
下图以C#为例,说明整个过程, C++, Java, Objective-C, ActionScript与其类似。
PHP也需要Slice编译的步奏。但Ruby,Python可以不编译,他们可以动态的加载Slice定义。
注意,客户端和服务器的唯一联系就是Slice定义。客户端和服务器可以由不同的小组,用不同的语言进程开发。
下面我们将用C#来开发一个完整的客户端和服务器。你马上就会看到,只要写几行代码,就可以实现一个简单的分布式应用。
Slice的编译器都在C:\Program Files (x86)\ZeroC\Ice-3.5.1\bin中
C#的编译器在C:\Windows\Microsoft.NET\Framework64\v4.0.30319中
为了方便之后的编译,把这些目录都添加到系统变量PATH中。
我们的程序非常简单,客户端发给服务器一个字符串,服务器将字符串变成大写的然后发回去。虽然这个程序很简单,但他演示的实际步骤和我们开发分布式应用时所做的是一样的。因为这个程序非常小,所以大部分的代码都是用来初始化和结束Ice运行时的模板代码,这些代码可以被其他的大型程序所重用。1. 用Slice(Specification Language for Ice)定义类型和接口。
Slice定义了服务器和客户端之间传输数据的类型和服务器提供的分布式对象的接口。
我们定义个一个接口如下
// File example.ice
module Example
{
interface Converter
{
string toUpper(string s);
};
};
注意这个定义封闭在module Example中。Slice模块(Slice Module)和命名空间或包的作用是一样的。一个模块可以用在不同的源文件中,这对大型开发团队的解耦非常有帮助。开发人员可以各自修改Slice定义中不同的部分,不会因为一个小改变就使整个系统重新编译。
2.编译Slice定义
使用slice2cs(Slice-to-C#编译器),我们可以将Slice定义编译为C#源文件。
slice2cs example.ice
这个命令,将example.ice编译为C#源文件example.cs。
3.编写客户侧代码
using Example;
public class Client
{
public static void Main(string[] args)
{
try
{
//客户端初始化ICE运行时,返回一个Communicator对象,代表一个Ice运行时的实例。
Ice.Communicator communicator = Ice.Util.initialize();
/*客户端将字符串converter:tcp -p 10000 -h 127.0.0.1转换为一个代理。这个代理代表了一个服务器提供的远程对象。checkedCast将代理的类型由Ice.ObjectPrx转变为Example.ConverterPrx。
converter:tcp -p 10000 -h 127.0.0.1:代表连接127.0.0.1的10000端口
Ice location service,可以使客户端不用任何物理信息就能找到服务器,所以这里可以不写物理地址。*/
ConverterPrx cvt = ConverterPrxHelper.checkedCast(
communicator.stringToProxy("converter:tcp -p 10000 -h 127.0.0.1"));
//客户端通过调用cvt.toUpper,发送"hello world"给服务器,并从服务器接到返回的值。
string upper = cvt.toUpper("hello world");
System.Console.WriteLine("Server returned: " + upper);
//destroy用来结束运行时
communicator.destroy();
}
catch (System.Exception ex)
{
System.Console.Error.WriteLine(ex);
System.Environment.Exit(1);
}
}
}这段代码很简单,string upper = cvt.toUpper("hello world");完成了一切工作:建立连接,发送消息给服务器,取得服务器返回的消息,传输中如果有错误发生,将抛出相应的异常。
将C:\Program Files (x86)\ZeroC\Ice-3.5.1\Assemblies\Ice.dll
和C:\Program Files (x86)\ZeroC\Ice-3.5.1\bin\x64\bzip2.dll(这里的CSC使用的是64位,C:\Windows\Microsoft.NET\Framework64\v4.0.30319)
将examle.cs和client.cs编译为exe。运行命令
csc /r:Ice.dll client.cs example.cs
得到client.exe
编写服务器代码
服务端,必须要实现toUpper方法以供客户端调用。
public class ConverterI : Example.ConverterDisp_
{
public override string toUpper(string s, Ice.Current c)
{
return s.ToUpper();
}
}注意我们定义的类从Example.ConverterDisp_继承。这个基类是由slice2cs(Slice-to-C#编译器)生成的。
剩下的任务就是初始化和结束Ice运行时。这部分代码几乎和客户端的一样。只是,服务器创建的是对象适配器(object adapter,用来监听请求),而不是代理,在这个适配器上添加一个ConverterI 对象。还有,服务器调用waitForShutdown来等待Ice运行时的关闭。(一般,关闭都是由一个信号或者服务器上另外一个线程的代码来发起)
public class Server
{
public static void Main(string[] args)
{
try
{
Ice.Communicator communicator = Ice.Util.initialize();
Ice.ObjectAdapter adapter = communicator.createObjectAdapterWithEndpoints(
"converter", "tcp -p 10000");
adapter.add(new ConverterI(), communicator.stringToIdentity("converter"));
adapter.activate();
communicator.waitForShutdown();
communicator.destroy();
}
catch(System.Exception ex)
{
System.Console.Error.WriteLine(ex);
System.Environment.Exit(1);
}
}
}这里,我们把监听端口号写死,是为了说明的便利。Ice location service可以自动的给服务端分配一个未使用的端口,并且客户端也能在不知道服务端的IP和端口号的情况下连接上服务端。
最后编译程序。
csc /r:Ice.dll server.cs example.cs
运行server.exe 和 client.exe。就能看到结果。
本文介绍了ICE编程模型的四个步骤,包括使用Slice定义类型和接口,编译Slice为C#等语言,以及编写客户端和服务器。通过C#示例展示了如何实现一个简单的分布式应用,并提到了不同语言的处理方式,如PHP需要编译而Ruby和Python则不需要。文章还提及了Slice编译器和C#编译器的路径,以及将这些路径添加到系统变量PATH中的建议。
 ICE 编程模型&spm=1001.2101.3001.5002&articleId=22854757&d=1&t=3&u=75f1ef18fc8d4af18c6a5ee308fe20dd)
749

被折叠的 条评论
为什么被折叠?



