ICE专题:使用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(www.wishgame.com) 的通信引擎。关于Ice的详细介绍,可参考以下资料:
* 《反叛之冰:Internet Communications Engine》 - http://blog.csdn.net/grhunter/archi...7/20/45606.aspx
* 《ICE之父抵京讲解高性能网络计算引擎》 - http://www.csdn.net/news/newstopic/16/16366.shtml
* 2004年第9期《程序员》杂志上的Ice专题 - http://mag.csdn.net/Content.aspx?ID...dd-0b3e55740577



本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/sgsoft/archive/2007/05/02/734456.html,如需转载请自行联系原作者

相关文章
|
1月前
|
消息中间件 网络协议 C#
C#使用Socket实现分布式事件总线,不依赖第三方MQ
`CodeWF.EventBus.Socket` 是一个轻量级的、基于Socket的分布式事件总线系统,旨在简化分布式架构中的事件通信。它允许进程之间通过发布/订阅模式进行通信,无需依赖外部消息队列服务。
C#使用Socket实现分布式事件总线,不依赖第三方MQ
|
27天前
|
编译器 C#
c# - 运算符<<不能应用于long和long类型的操作数
在C#中,左移运算符的第二个操作数必须是 `int`类型,因此需要将 `long`类型的位移计数显式转换为 `int`类型。这种转换需要注意数据丢失和负值处理的问题。通过本文的详细说明和示例代码,相信可以帮助你在实际开发中正确使用左移运算符。
31 3
|
26天前
|
编译器 C#
c# - 运算符<<不能应用于long和long类型的操作数
在C#中,左移运算符的第二个操作数必须是 `int`类型,因此需要将 `long`类型的位移计数显式转换为 `int`类型。这种转换需要注意数据丢失和负值处理的问题。通过本文的详细说明和示例代码,相信可以帮助你在实际开发中正确使用左移运算符。
37 1
|
1月前
|
人工智能 文字识别 Java
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
尼恩,一位拥有20年架构经验的老架构师,通过其深厚的架构功力,成功指导了一位9年经验的网易工程师转型为大模型架构师,薪资逆涨50%,年薪近80W。尼恩的指导不仅帮助这位工程师在一年内成为大模型架构师,还让他管理起了10人团队,产品成功应用于多家大中型企业。尼恩因此决定编写《LLM大模型学习圣经》系列,帮助更多人掌握大模型架构,实现职业跃迁。该系列包括《从0到1吃透Transformer技术底座》、《从0到1精通RAG架构》等,旨在系统化、体系化地讲解大模型技术,助力读者实现“offer直提”。此外,尼恩还分享了多个技术圣经,如《NIO圣经》、《Docker圣经》等,帮助读者深入理解核心技术。
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
|
1月前
|
存储 开发框架 .NET
C#语言如何搭建分布式文件存储系统
C#语言如何搭建分布式文件存储系统
73 2
|
24天前
|
编译器 C#
c# - 运算符<<不能应用于long和long类型的操作数
在C#中,左移运算符的第二个操作数必须是 `int`类型,因此需要将 `long`类型的位移计数显式转换为 `int`类型。这种转换需要注意数据丢失和负值处理的问题。通过本文的详细说明和示例代码,相信可以帮助你在实际开发中正确使用左移运算符。
12 0
|
2月前
|
存储 NoSQL Java
分布式session-SpringSession的应用
Spring Session 提供了一种创建和管理 Servlet HttpSession 的方案,默认使用外置 Redis 存储 Session 数据,解决了 Session 共享问题。其特性包括:API 及实现用于管理用户会话、以应用容器中性方式替换 HttpSession、简化集群会话支持、管理单个浏览器实例中的多个用户会话以及通过 headers 提供会话 ID 以使用 RESTful API。Spring Session 通过 SessionRepositoryFilter 实现,拦截请求并转换 request 和 response 对象,从而实现 Session 的创建与管理。
分布式session-SpringSession的应用
|
1月前
|
消息中间件 网络协议 安全
C# 一分钟浅谈:WebSocket 协议应用
【10月更文挑战第6天】在过去的一年中,我参与了一个基于 WebSocket 的实时通信系统项目,该项目不仅提升了工作效率,还改善了用户体验。本文将分享在 C# 中应用 WebSocket 协议的经验和心得,包括基础概念、C# 实现示例、常见问题及解决方案等内容,希望能为广大开发者提供参考。
110 0
|
1月前
|
缓存 网络协议 API
分布式系统应用之服务发现!
分布式系统应用之服务发现!
|
1月前
|
Web App开发 网络协议 API
基于C#编写一个远程桌面应用
基于C#编写一个远程桌面应用
44 0
下一篇
无影云桌面