zoukankan      html  css  js  c++  java
  • 使用C#编写ICE分布式应用程序

    原文来自blogCentaur 随笔录使用C#编写Ice应用程序,原文程序中没有注释,我参照马维达翻译的ICE分布式程序设计Ice-1.3.0-C.pdf,里面的代码有C++和Java的,没有C#的,计划平时有空学习ICE的C#程序设计,将相应的代码使用C#编写,算是学习ICE吧,今天第一个程序就是HelloWord应用:
    C#开发环境的搭建参照使用C#编写Ice应用程序。补充一点是设置Path目录中增加ice-1.5.1和增加环境变量ICE_HOME

     

    1、编写任何Ice 应用的第一步都是要编写一个Slice 定义,其中含有应用所

    用的各个接口。我们为我们的小打印应用编写了这样的Slice 定义:

    Hello World 应用

    interface Printer

    {

    void printString(string s);

    };

    我们把这段文本保存在叫作Printer.ice 的文件中。

    我们的Slice 定义含有一个接口,叫作Printer。目前,我们的接口非常简单,只提供了一个操作,叫作printString。printString 操作接受一个串作为它唯一的输入参数;这个串的文本将会出现在(可能在远地的)打印机上。

    2、编写用于C# Slice 定义

    要创建我们的C# 应用,第一步是要编译我们的Slice 定义,生成C#代理和骨架。在Windows上,你可以这样编译定义:

    slice2cs.exe Printer.ice

    slice2cs 编译器根据这个定义生成一些.cs 源文件。我们目前无需关注这些文件的确切内容——它们包含的是编译器生成的代码,与我们在Printer.ice 中定义的Printer 接口相对应。

    3、编写和编译服务器

    要实现我们的Printer 接口,我们必须创建一个servant 类。按照惯例,

    servant 类的名字是它们的接口的名字加上一个I 后缀,所以我们的servant

    类叫作PrinterI,并放在PrinterI.cs 源文件中:

    using System;

    namespace IceTest

    {

    /// <summary>

    /// 要实现我们的Printer 接口,我们必须创建一个servant 类。按照惯例,

    ///servant 类的名字是它们的接口的名字加上一个I 后缀,所以我们的servant

    ///类叫作PrinterI,PrinterI 类继承自叫作_PrinterDisp 的基类。这个基类由

    ///slice2cs 编译器生成,是一个抽象类,其中含有一个printString

    ///方法,其参数是打印机要打印的串,以及类型为Ice.Current 的对象

    ///我们的printString 方法的实现会简单地把它的参数写到终端。

    /// </summary>

    public class PrinterI :_PrinterDisp

    {

    public PrinterI()

    {

    //

    // TODO: 在此处添加构造函数逻辑

    //

    }

    public override void printString(string s, Ice.Current __current)

    {

    System.Console.WriteLine(s);

    }

    }

    }

    PrinterI 类继承自叫作_PrinterDisp 的基类。这个基类由slice2cs 编译器生成,是一个抽象类,其中含有一个printString方法,其参数是打印机要打印的串,以及类型为Ice.Current 的对象.我们的printString 方法的实现会简单地把它的参数写到终端。

    服务器代码的其余部分在一个叫作Server.cs 的源文件中,下面给出了其完整代码:

    using System;

    namespace IceTest

    {

    /// <summary>

    /// Server 的摘要说明。

    /// </summary>

    public class Server

    {

    public Server()

    {

    //

    // TODO: 在此处添加构造函数逻辑

    //

    }

    public static void Main(string[] args)

    {

    int status = 0;

    Ice.Communicator ic = null;

    try

    {

    //初始化Ice runtime ,将args传递给这个调用,是因为服务器可能

    //有run time感兴趣的命令行参数,返回的是一个Ice.Communicator

    //它是Ice run time的主句柄

    ic = Ice.Util.initialize(ref args);

    //调用createObjectAdapterWithEndpoints创建一个对象适配器,传入的参数为SimplePrinter(适配器名称)

    //和default -p 10000或者是适配器使用缺省协议TCP/IP在端口10000侦听到来的请求

    Ice.ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints("SimplePrinter","default -p 10000");

    //这时,服务器端run time 已经初始化,我们实例化一个PrinterI 对

    //象,为我们的Printer 接口创建一个servant。

    Ice.Object obj = new PrinterI();

    //我们调用适配器的add,告诉它有了一个新的servant ;传给add 的参

    //数是我们刚才实例化的servant,再加上一个标识符。在这里,

    //"SimplePrinter" 串是servant 的名字(如果我们有多个打印机,每个

    //打印机都会有不同的名字,更正确的说法是,都会有不同的对象标识)。

    adapter.add(

    obj,Ice.Util.stringToIdentity("SimplePrinter"));

    //我们调用适配器的activate 方法激活适配器(适配器一开

    //始是在扣留(holding)状态创建的;这种做法在下面这样的情况下很

    //有用:如果我们有多个servant,它们共享同一个适配器,而在所有

    //servant 实例化之前我们不想处理请求)。一旦适配器被激活,服务器就

    //会开始处理来自客户的请求。

    adapter.activate();

    //调用waitForShutdown。这个方法挂起发出调用的线程,

    //直到服务器实现终止为止——或者是通过发出一个调用关闭run time,

    //或者是对某个信号作出响应(目前,当我们不再需要服务器时,我们

    //会简单地在命令行上中断它)。

    ic.waitForShutdown();

    }

    catch (Exception e)

    {

    Console.Error.WriteLine(e);

    status = 1;

    }

    finally

    {

    if (ic != null)

    ic.destroy();

    }

    Environment.Exit(status);

    }

    }

    }

    Main 的主体含有一个try 块,我们把所有的服务器代码都放在其中;然后是两个catch 处理器。第一个处理器捕捉Ice run time 可能抛出的所有异常,其意图是,如果代码在任何地方遇到意料之外的Ice 运行时异常,栈会一直退回到Main,打印出异常,然后把失败返回给操作系统。第二个处理器捕捉串常量,其意图是,如果我们在代码某处遇到致命错误,我们可以简单地抛出带有出错消息的串文本。这也会使栈退回到main,打印出出错消息,然后把失败返回给操作系统。

    这段代码会在退出之前销毁通信器(如果曾经成功创建过)。要使Ice run time 正常结束,这样做是必需的:程序必须调用它所创建的任何通信器的destroy ;否则就会产生不确定的行为。我们把对destroy 的调用放进finally 块,这样,不管前面的try 块中发生什么异常,通信器都保证会正确销毁。

    4、编写和编译客户

    客户代码在Client.cs 中,看起来与服务器非常类似。下面是完整

    的代码:

    using System;

    namespace IceClientTest

    {

    /// <summary>

    /// Client 的摘要说明。

    /// </summary>

    public class Client

    {

    public Client()

    {

    //

    // TODO: 在此处添加构造函数逻辑

    //

    }

    public static void Main(string[] args)

    {

    int status = 0;

    Ice.Communicator ic = null;

    try

    {

    //调用Ice::initialize 初始化Ice run time。

    ic = Ice.Util.initialize(ref args);

    //获取远地打印机的代理。我们调用通信器的stringToProxy

    //创建一个代理,所用参数是"SimplePrinter:default -

    //p 10000"。注意,这个串包含的是对象标识和服务器所用的端口号

    Ice.ObjectPrx obj = ic.stringToProxy(

    "SimplePrinter:default -p 10000");

    //stringToProxy 返回的代理的类型是Ice::ObjectPrx,这种类型

    //位于接口和类的继承树的根部。但要实际与我们的打印机交谈,我们需

    //要的是Printer 接口、而不是Object 接口的代理。为此,我们需要调

    //用PrinterPrxHelper.checkedCast 进行向下转换。这个方法会

    //发送一条消息给服务器,实际询问“这是Printer 接口的代理吗?”如

    //果是,这个调用就会返回Printer 的一个代理;如果代理代表的是其他

    //类型的接口,这个调用就会返回一个空代理。

    PrinterPrx printer

    = PrinterPrxHelper.checkedCast(obj);

    //测试向下转换是否成功,如果不成功,就抛出出错消息,终止客户。

    if (printer == null)

    throw new ApplicationException("Invalid proxy");

    //我们的地址空间里有了一个活的代理,可以调用printString 方法,

    //把享誉已久的 "Hello World!" 串传给它。服务器会在它的终端上打印这个串。

    printer.printString("Hello World!");

    }

    catch (Exception e)

    {

    Console.Error.WriteLine(e);

    status = 1;

    }

    finally

    {

    if (ic != null)

    ic.destroy();

    }

    Environment.Exit(status);

    }

    }

    }

     

    Reference:

    Ice (Internet Communications Engine)是由前CORBA专家Marc Laukien、Michi Henning及Matthew Newhook等人开发的新一代面向对象中间件,已被用作大型在线游戏Wish(http://www.wishgame.com/) 的通信引擎。关于Ice的详细介绍,可参考以下资料:
    * 《反叛之冰:Internet Communications Engine》 - http://blog.csdn.net/grhunter/archive/2004/07/20/45606.aspx
    * 《ICE之父抵京讲解高性能网络计算引擎》 - http://www.csdn.net/news/newstopic/16/16366.shtml
    * 2004年第9期《程序员》杂志上的Ice专题 - http://mag.csdn.net/Content.aspx?ID=0ded903a-0467-437a-b2dd-0b3e55740577

  • 相关阅读:
    巴洛克式和哥特式的区别
    推荐阅读书籍,是时候再行动起来了。
    AtCoder ABC 159F Knapsack for All Segments
    AtCoder ABC 159E Dividing Chocolate
    AtCoder ABC 158F Removing Robots
    AtCoder ABC 158E Divisible Substring
    AtCoder ABC 157F Yakiniku Optimization Problem
    AtCoder ABC 157E Simple String Queries
    AtCoder ABC 157D Friend Suggestions
    AtCoder ABC 156F Modularness
  • 原文地址:https://www.cnblogs.com/adylee/p/1324845.html
Copyright © 2011-2022 走看看