CORBA学习与实践
1、简述:
来自百度百科的一个描述,CORBA(Common Object Request Broker Architecture,公共对象请求代理体系结构,通用对象请求代理体系结构)是由OMG组织制订的一种标准的面向对象应用程 序体系规范。或者说 CORBA体系结构是对象管理组织(OMG)为解决分布式处理环境(DCE)中,硬件和软件系统的互连而提出的一种解决方案;OMG组织是一个国际性的非盈利组织,其职责是为应用开发提供一个公共框架,制订工业指南和对象管理规范,加快对象技术的发展。
2、对象管理体系结构:
对象管理体系结构OMA(Object Management Architecture )的参考模型。它从总体上抽象地描述了OMG组织推出的面向对象技术所包含的内容,以及模型中各组成部分之间的关系。CORBA规范定义了接口定义语言IDL (Interface Definition Language )及其与某些其他语言的映射、单个对象请求代理ORB(Object Request Broker)和ORB间互操作机制。
对象管理体系结构:
对象请求代理ORB:对象请求代理负责对象在分布环境中透明的收发请求和响应,它是构建分布对象应用、在异构或同构环境下实现应用间互操作的基础。
对象服务(Object Services):对象服务是为使用和实现对象而提供的基本服务集合。针对对象服务,OMG组织制订了CORBA服务规范,简称COSS规范(Common Object Services Specification)。COSS规范由一组接口(Interface)和相应的服务描述构成。
公共设施(Common Facilities):公共设施是向应用开发提供的一组共享服务接口,但这组服务不像对象服务那样基本。
应用接口(Application Interfaces):应用接口是由软件销售商提供的、可控制其接口的产品。应用接口处于参考模型的最高层。
域接口(Domain Interfaces):域是指一个范围,在其中的对象具有公共的特征,遵从公共的规则。一个域可以是一个单独的ORB系统,在其中的对象具有公共的对象引用、网络地址、保密机制等;一个域也可以跨越多个ORB系统,ORB内的对象具有公共的特征。一个ORB系统内部也可以划分为多个域。域接口是为应用领域服务而提供的接口。
3、ORB的体系结构
(1)IDL语言通过说明对象的接口来定义对象。一个接口包括一组命名的操作和相应于这些操作的参数。
(2)ORB核心提供了客户与对象之间实现透明通信的方法,它可以屏蔽对象实现位置、实现方法、状态和通信机制等细节以及不同实现间可能存在的差异。
(3)对象适配器OA(Object Adaptor)位于各个ORB内核和对象实现之间,它负责服务对象的注册、对象引用的创建和解释、对象实现的服务进程(或线程)的创建和撤消、对象的构造和撤消以及客户请求的分发。
(4)IDL Stub为客户提供了静态调用方式,IDL Skeleton与Java RMI服务者Stub类似,为服务方提供了静态实现方式。IDL编译器编译描述服务对象接口的IDL文件,生成对应于具体编程语言的IDL Stub和IDL Skeleton程序。IDL Skeleton 对用户请求进行反序列化,定位所请求的对象的方法,执行要求的方法,并把执行结果或异常信息序列化后发送回客户。
(5)动态调用接口DII(Dynamic Invocation Interface)和动态构架接口DSI(Dynamic Skeleton Interface)提供了动态调用方式和动态实现方式。
4、ORB运行原理
在单个ORB支撑的环境中,操作步骤大致如下:
1. 客户通过某种方式找到特定对象实现的对象引用,这些查询方式包括:
(1)使用ORB接口中提供的操作。
当ORB初次启动时,客户并不知道它要调用的对象实现的对象引用。没有对象引用就不能定位对象实现,也就不能进行调用请求。因此,ORB给出了获取初始对象引用的方法,应用可以通过调用它来获得初始化对象引用。ORB接口获取初始对象引用的操作以ORB对象的操作的形式出现。
(2) 使用CORBA对象服务中的命名服务。
(3) 通过其他接口的输出参数或者返回值。
(4) 通过ORB实现系统自身提供的特定的对象引用获取方法。
2.如果该对象实现有相应的IDL Stub,则客户可以通过该IDL Stub向对象实现发出请求。否则,在接口库的协助下,客户可以使用动态调用接口来向对象实现发出请求。
3.当对象调用请求通过IDL Stub或动态调用接口到达ORB核心以后,ORB核心负责请求的传送,将其送给相应的对象适配器,其具体的请求传递方式由ORB的具体实现决定。
4.对象适配器接到该请求后,判断一下所请求的对象实现是否有IDL Skeleton存在。如果有,则对象适配器通过该IDL Skeleton架调用执行对象实现中的操作;否则,对象适配器将通过动态构架接口中的动态实现例程(DIR)来调用对象实现中的操作。
5.对象实现的特定操作方法执行完成后,结果(包括输出参数、输入输出参数、返回值以及异常信息等)将按照对象请求传递和执行路径逆向返回给客户对象。至此,一个完整的对象请求调用便完成了。
包含多个异构ORB系统的环境中,客户可以通过自己所在的ORB系统向其他ORB系统上的对象实现发出调用请求,其具体的执行步骤略有不同,但各个ORB系统内的对象请求处理过程也是和上面过程一样的。
5、IDL语言
IDL语言是一种接口定义语言。IDL语言不同于所有已有的程序设计语言,它是一种描述性语言,也就是说,用它描述得到的接口是不能直接被编译执行。
OMG IDL语言采用ISOLatin-1(8859.1)字符集。该字符集可以分为字母、数字、图形符号、空格符、和格式符号。其中字母包括英文26个字母的大小写,数字包括10个阿拉伯数字0到9。
6、idlj命令介绍:
idlj命令是把idl文件生成java代码,此命令在JDK的安装目录的bin目录下可以找到
idlj命令的使用语法如下:
idlj [选项] <idl文件>
其中,<idl 文件> 是包含 IDL 定义的文件的名称,而[选项] 是以下所列选项的任一组合。这些选项是可选的,并且可以以任意顺序显示;<idl 文件> 是必须的并且必须显示在最后。
7、orbd命令介绍
orbd是用来使客户能够透明地查找和调用持久对象在服务器上应用环境,各个参数如下:
sun关于orbd的介绍文档地址如下:http://download.oracle.com/javase/1.4.2/docs/guide/idl/orbd.html
8、对于整数的加减法的实现操作的接口,写idl文件LR.idl
module LR{ interface Op{ long add(in long a, in long b) ; long sub(in long a,in long b) ; }; };
9、执行idlj命令,实现idl到java的实现:
10、这样的情况就成功了。会在D:\test\test文件夹中多出了一个文件夹LR。进入LR文件夹中,查看LR文件中有6个java文件。
Holder类(支持类)
所有的IDL标准类型和自定义类型都映射为相应的Holder类。所有IDL基本数据类型的Holder类都在org.omg.CORBA包中定义,所有自定义的类型名,除了那些由typedef定义的外,都映射有相应的Holder类。Holder类的作用主要是为远程方法参数传递提供支持。
Helper类(帮助类)
所有用户自定义的IDL类型(如<UserType> )都会映射为一个相应的< UserType >Helper类。它提供了几种静态方法,包括该类型对象的插入和获取操作、获得对象在接口库中的标识(repository id)、获得TypeCode操作,以及把该类型对象写入输出流或从输入流中读出的操作。另外,Helper类还定义了narrow操作,实现对象名到对象的映射。
11、编写OpImpl.java类,对接口OpPOA的继承:
import LR.OpPOA; public class OpImpl extends OpPOA { @Override public int add(int a , int b) { return ( a + b ); } @Override public int sub(int a , int b) { return ( a - b ); } }
12、编写服务器端,OpServer.java.
import org.omg.CORBA.ORB; import org.omg.CosNaming.NameComponent; import org.omg.CosNaming.NamingContextExt; import org.omg.CosNaming.NamingContextExtHelper; import org.omg.PortableServer.POA; import org.omg.PortableServer.POAHelper; import LR.Op; import LR.OpHelper; public class OpServer { private static String strPort = "-ORBInitialPort" ; private static String numPort = "1050" ; //启动ORB以及等待远程客户机的调用的代码 public static void main(String args[]) throws Exception { // -ORBInitialPort args = new String[2]; args[0] = strPort; args[1] = numPort;//端口 // 初始化ORB ORB orb = ORB.init(args, null); System.out.println("初始化ORB!"); // 取根POA的引用,并激活POAManager org.omg.CORBA.Object obj=orb.resolve_initial_references("RootPOA"); System.out.println("取根POA引用"); POA rootpoa = POAHelper.narrow(obj); System.out.println("调用了narrow函数") ; rootpoa.the_POAManager().activate(); System.out.println("激活POAManager"); // 创建一个Impl实例 OpImpl opImpl = new OpImpl(); System.out.println("创建了接口的实例"); // 从服务中得到对象的引用 org.omg.CORBA.Object ref = rootpoa.servant_to_reference(opImpl); Op href = OpHelper.narrow(ref); System.out.println("从服务中得到对象引用"); // 得到一个根名称的上下文 org.omg.CORBA.Object objRef = orb .resolve_initial_references("NameService"); NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef); System.out.println("得到根名称的上下文"); // 在命名上下文中绑定这个对象 String name = "Op"; NameComponent path[] = ncRef.to_name(name); ncRef.rebind(path, href); System.out.println("在根名称的上下文绑定实例对象"); System.out.println("启动线程服务,等待客户端调用"); // 启动线程服务,等待客户端调用 orb.run(); } }
13、编写服务器端,OpClient.java.
import LR.Op; import LR.OpHelper; import org.omg.CORBA.ORB; import org.omg.CORBA.ORBPackage.InvalidName; import org.omg.CosNaming.NamingContextExt; import org.omg.CosNaming.NamingContextExtHelper; import org.omg.CosNaming.NamingContextPackage.CannotProceed; import org.omg.CosNaming.NamingContextPackage.NotFound; public class OpClient { private static Op op; static { System.out.println("客户端的初始化配置开始"); //参数设置 -ORBInitialHost 127.0.0.1 -ORBInitialPort 1050 String args[] = new String[4]; args[0] = "-ORBInitialHost"; args[1] = "127.0.0.1";// 服务端的IP地址 args[2] = "-ORBInitialPort"; args[3] = "1050";// 服务端的端口 // 初始化 ORB orb = ORB.init(args, null); // 获取根名称上下文 org.omg.CORBA.Object objRef = null; try { objRef = orb.resolve_initial_references("NameService"); } catch (InvalidName e) { e.printStackTrace(); } NamingContextExt neRef = NamingContextExtHelper.narrow(objRef); String name = "Op"; //注意这个是接口来的 try { op = OpHelper.narrow(neRef.resolve_str(name)); } catch (NotFound e) { e.printStackTrace(); } catch (CannotProceed e) { e.printStackTrace(); } catch (org.omg.CosNaming.NamingContextPackage.InvalidName e) { e.printStackTrace(); } System.out.println("客户端的初始化配置结束"); } public static void main(String args[]) throws Exception { test(1,2) ; } public static void test(int a,int b) { System.out.println("add(1,2) result="+op.add(a,b)); System.out.println("sub(1,2) result="+op.sub(a,b)) ; } }
14、编译所有java类
javac *.java
编译之后,在相应的文件夹中就会出玩了相对应的class文件。
15、启动orbd
16、看看是否启动了1050端口
17、启动服务器
18、运行客户端
好了,整个过程也就算是成功了。
下一篇: 黑莓合伙人基金向三家科技创业公司投资
推荐阅读
-
MVC5项目转.Net Core 2.2学习与填坑记录(1)
-
php学习笔记 类的声明与对象实例化
-
学习TypeScript,笔记一:TypeScript的简介与数据类型
-
Python机器学习之scikit-learn库中KNN算法的封装与使用方法
-
C#接口与抽象类学习笔记
-
荐 14天数据分析与机器学习实践之Day02——数据分析处理库Pandas应用总结
-
SEO真正需要的是实践 而非机械的学习别人的理论
-
python学习笔记--深拷贝与浅拷贝的区别
-
《C语言及程序设计初步》_1.11算术运算符与算术表达式_实践9——分离各位数
-
Python机器学习库scikit-learn安装与基本使用教程