CORBA介绍

来源:互联网 发布:济宁seo公司 编辑:程序博客网 时间:2024/04/29 18:21

      CORBA(Common Object Request Broker Architecture)通用对象请求代理体系结构:是在当今快速发展的软件与硬件资源的情况下发展出的一种新技术。它可以让分布的应用程序完成通信,无论这种应用程序是什么厂商生产的,只要符合CORBA标准就可以相互通信。CORBA1.1于1991年由OMG提出,同时还提出了接口定义语言Interface Definition Language(即IDL)以及能够让客户/服务器对象在特定的ORB(对象请求代理)实现中进行通信。而1994年提出并被采纳的CORBA 2.0标准才真正实现了不同生产厂商间的互操作性。

      ORB是一个在对象间建立客户/服务器联系的中间件。使用ORB,客户端可以调用服务器的对象或对象中的应用,被调用的对象不要求在同一台机器上。由ORB负责进行通信,同时ORB也负责寻找适于完成这一工作的对象,并在服务器对象完成后返回结果。客户对象完全可以不关心服务器对象的位置、实现它所采用的具体技术和工作的硬件平台,甚至不必关心服务器对象的与服务无关的接口信息,这就大大简化了客户程序的工作。既然能够这么方便,那ORB就需要提供在不同机器间应用程序间的通信,数据转换,并提供多对象系统的无缝连接。

      我们通常编制客户/服务器程序时,常常需要自己定义通信协议,而协议的制定往往与硬件和实现的方法有关,而ORB能够简化这一过程。在ORB下,协议通过IDL语言进行定义,保证了一致性, 为了照顾到灵活性,ORB允许程序员选择相应的操作系统,执行环境和编程语言。更重要的是它可以使原来的代码通过一定的方式重用。CORBA是面向对象标准的第一步,有了这个标准,软件的实现与工作环境对用户和开发者不再重要,可以把精力更多地放在本地系统的实现与优化上。

     下面我们来看看CORBA的一些具体情况。CORBA被设计用来对不同对象系统进行集成,提供灵活的的对象调用与功能实现。下图是客户对象通过ORB调用服务器对象。

    对象请求代理结构的大体工作过程就像上面的工作过程一样。客户将需要完成的工作交给ORB,由ORB决定由哪一个对象实例完成这个请求,然后激活这个对象, 将完成请求所需要的参数传送给这个激活的对象。除了客户传送参数的接口外,客户不需要了解其它任何信息,这就大大节省了用户的开发精力。而下图着重说明 ORB的接口结构。

      这个图中的一些信息希望大家能够注意一下,在编程的时候不一定能够全部用上,但是它们还是很重要的。在提出请求时,客户可以使用动态调用接口或者OMG IDL句柄。当然用户也可以直接调用一些ORB内部的功能。对象实现通过IDL产生的框架或通过动态框架接收到调用请求,在处理这些请求时,对象实现可以调用对象适配器和ORB。

      对象的接口有两种定义方式,可以使用接口定义语言(称为OMG接口定义语言,OMG IDL)进行静态定义,这种语言根据进行的操作和传送的参数定义对象。另一种方法,可以将接口加入接口库服务中,这种服务代表作为对象的接口的组件,允许在运行时对这些成为组件的接口进行访问,这两种方法是等效的。下图表示的是客户端使用句柄或动态调用接口进行访问的情况。

     客户知道对象的类型和希望进行的操作,客户端可以通过访问一个对象的对象参考提出请求。客户可以通过调用句柄函数初始化调用,也可以动态提出请求。动态发出的请求和通过句柄接口发出的静态请求两者在格式是一样的,请求的接收者不可能知道这种请求是动态发出的还是静态发出的。下图是一个对象实现接收请求的示意图。

     ORB定位合适的可以实现这个功能的代码,通过IDL框架或动态框架传向对象实现传送参数,并将控制权交给对象实现。框架是指定接口和对象适配器的,对于不同的接口和对象适配器是不同的。在实现请求的过程中,对象实现可以通过对象适配器获取一些ORB服务。在完成请求时,将控制权和输出数据返回给客户。不要被图给迷惑了,对象实现可以根据自己的需要选择需要的对象适配器使用。下图是接口和实现库的结构示意图。

     上图显示了接口和实现是如何对客户和对象实现是可用的,接口可以在OMG IDL或在接口库中实现,这种对接口的定义用于产生客户句柄和对象实现框架。对象实现信息在安装时提供,保存于实现库中,在传送请求时可以使用这个信息库中的内容。

     对象请求代理这个结构在上图中并不需要作为组件单独实现,它由接口定义。任何提供正确接口的ORB实现都是可被接受的。接口可分为以下几大类:

1. 对于所有ORB实现均相同的接口;

2. 指定于特定对象类型的操作;

3. 指定于对象实现的特定形式的操作;

      不同的ORB可以采用不同的实现策略,加上IDL编译器,库和不同的对象适配器,这一切提供了一系列对客户端的服务和对具有不同属性对象的实现。可以存在多个ORB实现,它们有不同的名称和不同的实现方法与调用方法,对于客户端而言,客户端可以同时访问由不同ORB实现管理的对象,当几个ORB共同工作时,它们必须能够区别它们各自的对象名(也就是对象参考),客户不管区别只管使用。ORB内核是ORB的一部分,它提供了对象的基本命名和请求通信机制。CORBA设计得可以支持不同的对象机制,它是通过在ORB内核上建立ORB来完成这一点的。

     一个对象的客户可以访问此对象参考,并对对象进行操作。客户不清楚对象的内部结构,它只知道对象的接口和执行操作所需要的时间和空间等资源。虽然我们可以把客户想象为一个调用对象的进程,但是我们也不要忘记了对象也可以调用其他对象的服务。客户端看到的ORB接口和人观念中的接口差不多,这就为编程提供了帮助。客户不需要对代码进行改变就可以通过ORB实现功能,对象适配器只能由ORB或对象实现调用。

     对象实现提供了对象的表现形式。通常实现由另一对象提供或由相应的软件提供,当然也可以自己编程实现。在某些情况下,对象的主要功能是非对象实体产生作用。在CORBA中可以支持对象的不同实现。通常,对象实现不依赖于ORB或客户请求,对象实现可以通过选择对象适配器选择和ORB相关服务来选择接口。

  对象参考是需要在ORB内指定的信息,客户和对象实现相应于语言映射有对象参考的一个透明定义,这样就把实现的表示与参考隔离开了。两个ORB实现可能在选择对象参考表示时是不同的。所有的ORB必须提供相对于对象参考一致的语言映射,这使得程序能够独立于ORB对对象参考进行访问。

      OMG接口定义语言(OMG IDL)通过对象的接口定义了对象的类型。一个接口由一些命名的操作和与这些操作相关的参数组成。请注意,虽然IDL提供概念框架用于描述对象,但不需要有IDL源代码供ORB工作。只要相同的信息以句柄函数或运行接口库的形式提供,特定的ORB就可以正常工作。IDL是一种方法,它使对象实现能够告诉潜在的客户,什么样的操作可以执行。从IDL的定义上可以将CORBA对象映射为特定的编程语言或对象系统。

    不同的面向对象语言和非面向对象语言可以以不同的方式访问CORBA对象。对于面向对象语言而言,它希望看到的是对象的形式,即使对非面向对象语言来说,它所希望看到的也不包括具体的内部实现。将OMG IDL映射为编程语言的方法对于所有的ORB实现应该是一致的。这些映射可能包括数据类型的映射和调用ORB的过程(或函数)接口的映射。语言映射还定义了对象调用和客户(或实现)中的控制线程之间的相互作用。最普通的映射提供了同步调用,结果可以在过程完成时返回。其它的映射可以用来初始化调用并将控制权返回给程序,在这些情况下,附加的函数必须相应的同步功能。

     为了映射非面向对象语言,将有一个对每个接口类型的程序接口。通常,句柄将提供访问OMG IDL定义的操作的机制。句柄调用对于ORB核心是私有的那部分ORB。如果有多于一个ORB,将会有对应于不同ORB的接口。在这种情况下,需要ORB和语言映射相互协调以访问正确的对象参考句柄。面向对象语言不需要句柄接口。接口允许对象动态调用,用户可以不必调用一个特定对象上的操作,他可以指定调用特定的对象。客户程序提供关于操作和参数类型的信息就可以了。

      允许动态处理对象调用的接口是非常有用的,不是由与特殊操作相关的框架来访问对象实现,而是由一个提供访问操作名和参数的界面用一种类似于动态调用接口的方式来访问对象实现。动态框架界面可以由客户句柄或动态调用接口来调用,它们向动态框架接口发出对象请求。动态框架接口的基本思想是让所有的对象请求通过调用同一组例程来达到调用对象实现中方法的目的,这组例程便叫做动态调用例程DIR

    对象适配器是对象实现访问ORB提供的服务的主要方式,由ORB提供的服务在一个对象适配器中经常包括:对象引用的产生和解释、方式调用、交互性安全、对象和实现的激活与释放、对象引用到实现的映射及实现的定位由于各个不同对象的对象粒度、生命周期等等。ORB内核无法为所有的对象提供一个统一、方便有效的界面。通过对象适配器的作用,可以将目的对象分成若干组,每组通过特定的对象适配器来满足其特定的需要,但这样一来,对象适配器的种类便会急剧膨胀,为了减少对象适配器的种类,CORBA给出了基本对象适配器(BOA),以满足大多数对象的需要,BOA提供了产生和解释对象引用、对请求进行认证、激活/去活实现、激活/去活单个对象、通过框架调用方法等功能在提供这些功能时,BOA要用到一些与操作系统有关的知识,这些知识由实现仓库提供,实现仓库还存放对象实现的有关信息。

    ORB接口是一种直接对应于ORB的接口,它对于所有的对象接口,对象适配器都是一样的。大部分的操作都由对象适配器,句柄,框架或动态调用实现,对于所有对象都需要的操作很少。接口库是一种服务,其中保存着接口信息,这些信息在ORB执行请求时会用得上。而且,当一个应用程序在调用一个未知接口的对象时,可以通过接口库了解能够在其上进行的操作。除了它可以充当ORB功能外,实现库通常还保存与ORB对象实现相关的信息。实现库包括了一些信息,这些信息让ORB可以定位并激活对象的实现。实现库中的信息是特定于ORB或实现环境的,通常,实现的安装和控制策略是通过实现库实现的。


一个完整的HelloWorld示例:

1)定义IDL:

   IDL没有的专门的开发工具,写起来容易出错,而且不美观,IDEA勉强支持语法高亮,但不支持格式化和语法校验。此处使用编写Hello.txt,然后修改文件名为Hello.idl,目录结构如图。

module HelloApp{     interface Hello{         string sayHello();         oneway void shutdown();     }; };


2)从IDL生成存根:

       进入IDL文件存放目录,然后执行:idlj -fall Hello.idl。


      命令执行完之后会生成若干java文件,此时目录结构如图所示。





3)实现IDL接口,开发服务端程序

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 HelloApp.Hello; import HelloApp.HelloHelper; import HelloApp.HelloPOA; class HelloImpl extends HelloPOA {     private ORB orb;     public void setORB(ORB orb_val) {             orb = orb_val;     }     // implement sayHello() method     public String sayHello() {             return "\nHello world !!\n";     }     // implement shutdown() method     public void shutdown() {             orb.shutdown(false);     } } public class HelloServer {     public static void main(String args[]) {         try {                 //创建一个ORB实例                 ORB orb = ORB.init(args, null);                 //得到一个RootPOA的引用,并激活POAManager                 POA rootpoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));                 rootpoa.the_POAManager().activate();                 // create servant and register it with the ORB                 //创建一个HelloImpl实例(servant),并注册到ORB上                 HelloImpl helloImpl = new HelloImpl();                 helloImpl.setORB(orb);                 //从服务中得到对象的引用                 org.omg.CORBA.Object ref = rootpoa.servant_to_reference(helloImpl);                 Hello href = HelloHelper.narrow(ref);                 //得到一个根名称的上下文                 org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");                 // Use NamingContextExt which is part of the Interoperable                 // Naming Service (INS) specification.                 NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);                 //在命名上下文中绑定这个对象                 String name = "Hello";                 NameComponent path[] = ncRef.to_name(name);                 ncRef.rebind(path, href);                 System.out.println("HelloServer ready and waiting ...");                 //启动线程服务,等待客户端的调用                 orb.run();         }catch (Exception e) {                 System.err.println("ERROR: " + e);                 e.printStackTrace(System.out);         }         System.out.println("HelloServer Exiting ...");     } }

4)实现CORBA的客户端:

import HelloApp.Hello; import HelloApp.HelloHelper; import org.omg.CORBA.ORB; import org.omg.CosNaming.NamingContextExt; import org.omg.CosNaming.NamingContextExtHelper; public class HelloClient {     static Hello helloImpl;     public static void main(String args[]) {             try {                     //创建一个ORB实例                     ORB orb = ORB.init(args, null);                     //获取根名称上下文                     org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");                     // Use NamingContextExt instead of NamingContext. This is                     // part of the Interoperable naming Service.                     NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);                     //从命名上下文中获取接口实现对象                     String name = "Hello";                     helloImpl = HelloHelper.narrow(ncRef.resolve_str(name));                     //调用接口对象的方法                     System.out.println("Obtained a handle on server object: " + helloImpl);                     System.out.println(helloImpl.sayHello());                     helloImpl.shutdown();             } catch (Exception e) {                     System.out.println("ERROR : " + e);                     e.printStackTrace(System.out);             }     }}

    目录结构如图所示:



5)运行:

    1>运行CORBA服务:



    2>运行CORBA应用的服务端:



    3>运行CORBA应用的客户端:



    此时CORBA应用的服务端:



转自:http://blog.csdn.net/woshizy/article/details/2786131

           http://lavasoft.blog.51cto.com/62575/240268/

0 0
原创粉丝点击