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间互操作机制。
对象管理体系结构:


CORBA学习与实践_第1张图片
对象请求代理ORB:对象请求代理负责对象在分布环境中透明的收发请求和响应,它是构建分布对象应用、在异构或同构环境下实现应用间互操作的基础。
对象服务(Object Services):对象服务是为使用和实现对象而提供的基本服务集合。针对对象服务,OMG组织制订了CORBA服务规范,简称COSS规范(Common Object Services Specification)。COSS规范由一组接口(Interface)和相应的服务描述构成。       
公共设施(Common Facilities):公共设施是向应用开发提供的一组共享服务接口,但这组服务不像对象服务那样基本。
应用接口(Application Interfaces):应用接口是由软件销售商提供的、可控制其接口的产品。应用接口处于参考模型的最高层。
域接口(Domain Interfaces):域是指一个范围,在其中的对象具有公共的特征,遵从公共的规则。一个域可以是一个单独的ORB系统,在其中的对象具有公共的对象引用、网络地址、保密机制等;一个域也可以跨越多个ORB系统,ORB内的对象具有公共的特征。一个ORB系统内部也可以划分为多个域。域接口是为应用领域服务而提供的接口。
3、ORB的体系结构


CORBA学习与实践_第2张图片
 (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 文件> 是必须的并且必须显示在最后。

CORBA学习与实践_第3张图片
 7、orbd命令介绍
orbd是用来使客户能够透明地查找和调用持久对象在服务器上应用环境,各个参数如下:

CORBA学习与实践_第4张图片
  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的实现:

CORBA学习与实践_第5张图片
 10、这样的情况就成功了。会在D:\test\test文件夹中多出了一个文件夹LR。进入LR文件夹中,查看LR文件中有6个java文件。

CORBA学习与实践_第6张图片
 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端口

CORBA学习与实践_第7张图片
 17、启动服务器

CORBA学习与实践_第8张图片
 18、运行客户端

CORBA学习与实践_第9张图片
 好了,整个过程也就算是成功了。

你可能感兴趣的:(分布式计算,corba)