`
isiqi
  • 浏览: 16004306 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

CORBA 程序设计指南(入门)(转载)

阅读更多

CORBA 程序设计指南(入门)(转载)

关键词corba 程序设计

CORBA 程序设计指南(入门)

Author: 龙湘明

Company: 北京邮电大学国家重点实验室

Date : 2001-2-28

Update : 2006-03-29

这里假设你对CORBA毫无所知。对JAVA略有所知,因为这里使用JAVA作为程序设计语言。学习了本书,你将对CORBA有个初步了解,并能编写一个简单完整的CORBA应用程序。

1.CORBA 简介

CORBACommon Object Request Broker Architecture)是为了实现分布式计算而引入的。为了说明CORBA在分布计算上有何特点,我们从它与其它几种分布计算技术的比较中进行说明。

与过去的面向过程的RPC(Remote Procedure Call)不同,CORBA是基于面向对象技术的,它能解决远程对象之间的互操作问题。MicroSoft DCOM (Distributed Component Object Model)也是解决这一问题的, 但它基于Windows操作系统,尽管到本书编写时,DCOM已有在其他操作系统如Sun Solaris, Digital Unix, IBM MVS 上的实现,但毫无疑问,只有在微软的操作系统上才会实现得更好。而只有CORBA是真正跨平台的,平台独立性正是CORBA的初衷之一。另一种做到平台无关性的技术是Java RMIRemote Method Invocation),但它只能用JAVA实现。CORBA与此不同,它通过一种叫IDLInterface Definition Language)的接口定义语言,能做到语言无关,也就是说,任何语言都能制作CORBA组件,而CORBA组件能在任何语言下使用。

因此,可以这样理解CORBACORBA一种异构平台下的语言无关的对象互操作模型。

1.1 CORBA体系结构

CORBA的体系结构如下:

1.1 CORBA体系结构

CORBA上的服务用IDL描述,IDL将被映射为某种程序设计语言如C++Java,并且分成两分,在客户方叫IDL Stub(桩), 在服务器方叫IDL Skeleton(骨架)。两者可以采用不同的语言。服务器方在Skeleton的基础上编写对象实现(Object Implementation),而客户方要访问服务器对象上的方法,则要通过客户桩。而双方又要通过而ORBObject Request Broker,对象请求代理)总线通信。

与传统的Client/Server模式(我们称为Two-tier client/server)不同,CORBA是一种multi-tier client/server architecture,更确切的说,是一种three-tier client/server模式。双重客户/服务器模式存在的问题是两者耦合太紧,它们之间采用一种私有协议通信,服务器的改变将影响到客户方。多重客户/服务器与此不同,两者之间的通信不能直接进行,而需要通过中间的一种叫代理的方式进行。在CORBA中这种代理就是ORB。通过它,客户和服务器不再关心通信问题,它们只需关心功能上的实现。从这个意义上讲,CORBA是一种中间件(Middleware)技术。

下面列出CORBA中的一些重要概念,或者说CORBA中的几个重要名词,有助于读者了解CORBA的一些重要的方面。

1.2 CORBA中的几个概念

1.2.1 ORBObject Request Broker

CORBA体系结构的核心就是ORB。可以这样简单理解:ORB就是使得客户应用程序能调用远端对象方法的一种机制。

1.2 ORB模型

具体来说就是:当客户程序要调用远程对象上的方法时,首先要得到这个远程对象的引用,之后就可以像调用本地方法一样调用远程对象的方法。当发出一个调用时,实际上ORB会截取这个调用(通过客户Stub完成,“提高”篇中会详细解释),因为客户和服务器可能在不同的网络、不同的操作系统上甚至用不同的语言实现,ORB还要负责将调用的名字、参数等编码成标准的方式(Marshaling)通过网络传输到服务器方(实际上在同一台机器上也如此),并通过将参数Unmarshaling的过程,传到正确的对象上(这整个过程叫重定向,Redirecting),服务器对象完成处理后,ORB通过同样的Marshaling/Unmarshaling方式将结果返回给客户。

因此,ORB是一种功能,它具备以下能力:

1.对象定位(根据对象引用定位对象的实现)

2.对象定位后,确信Server能接受请求

3.将客户方请求通过Marshaling/Unmarshing方式重定向到服务器对象上

4.如果需要,将结果以同样的方式返回。

1.2.2 IDL(Interface Definition Language)

IDL,接口定义语言,是CORBA体系中的另一个重要概念。如果说ORB使CORBA做到平台无关,那么IDL, 则使CORBA做到语言无关。

正像其名字中显示的那样,IDL仅仅定义接口,而不定义实现,类似于C中的头文件。实际上它不是真正的编程语言。要用它编写应用,需要将它映射它相应的程序设计语言上去,如映射到C++JAVA上去。映射后的代码叫Client Stub Code Server Skeleton Code

IDL的好处是使高层设计人员不必考虑实现细节而只需关心功能描述。IDL可以说是描述性语言。设计IDL的过程也是设计对象模型的过程。它是编写CORBA应用的第一步,在整个软件设计过程中至关重要。

IDL的语法很像C++,当然也像Java。很难想像一个程序设计人员是不懂CJava的,所以,几乎所有的程序设计人员都能迅速理解IDL。而这正是IDL设计者所希望的。

下面是一个IDL定义的简单例子:

// grid.idl
// IDL definition of a 2-D grid:
module simpleDemo{
interface grid {
 readonly attribute short height; // height of the grid 
readonly attribute short width; // width of the grid
 // IDL operations
 // set the element [row,col] of the grid, to value: 
void set(in short row, in short col, in long value);
 // return element [row,col] of the grid: 
long get(in short row, in short col); 
};
};

This IDL defines an interface for a grid CORBA object that maintains a grid or 2-D array of data values, which a client can access or modify remotely.

Module类似于Java中包(Package)的概念,实际上module simpleDemo映射到JAVA正是package simpleDemo。而Interface类似于C++中的类(classs)声明,或是Java中的Interface 定义。

附录中列出了IDL的全部语法。

1.2.3 Stub Code Skeleton Code

Stub code Skeleton Code 是由IDL Complier自动生成的,前者放在客户方,后者放在服务器方。不同厂商的IDL complier生成的Stub Skeleton会略有区别,但影响不大。

如上面的grid.idl, 编译后,Stub Code包含以下文件:

grid.java

_gridStub.java

gridHelper.java

gridHolder.java

gridOperations.java

Skeleton Code则包含以下文件:

gridOperations.java

gridPOA.java

gridPOATie.java

(在Stud Code 也包含gridOperations.java, 是因为在使用Call back机制时会用到。)

这些文件的用途后面会讲到。

1.2.4 GIOP IIOP

我们知道,客户和服务器是通过ORB交互的,那么,客户方的ORB和服务器方的ORB又是通过什么方式通信呢?通过GIOP(General Inter-ORB Protocol)。也就是说,GIOP是一种通信协议,它规定了两个实体:客户和服务器ORBs间的通信机制。

1.3 ORBs通信机制

GIOP在设计时遵循以下目标:

Ø Widest possible availability

Ø Simplicity

Ø Scalability

Ø Low cost

Ø Generality

Ø Architectural neutrality

也是说,GIOP设计的尽可能简单,开销最小,同时又具有最广泛的适应性和可扩展性,以适应不同的网络。

GIOP定义了以下几个方面:

1The Common Data Representation (CDR) definition.

通用数据表示定义。它实际上是IDL数据类型在网上传输时的编码方案。它对所有IDL数据类型的映射都作了规定。

2GIOP Message Formats.

它规定了ClientServer两个角色之间要传输的消息格式。主要包括RequestReply两种消息。

一个Request 消息有以下几部分组成:

A GIOP message header

A Request Header

The Request Body

相应的,一个Reply消息则包括

A GIOP message header

A Reply Header

The Reply Body

GIOP1.1规定 GIOP message header格式如下:

// GIOP 1.1

struct MessageHeader_1_1 {

char magic [4];

Version GIOP_version;

octet flags; // GIOP 1.1 change

octet message_type;

unsigned long message_size;

};

Request Header格式如下:

// GIOP 1.1

struct RequestHeader_1_1 {

IOP::ServiceContextList service_context;

unsigned long request_id;

boolean response_expected;

octet reserved[3]; // Added in GIOP 1.1

sequence <octet>object_key;</octet>

string operation;

Principal requesting_principal;

};

Request Body则按CDR规定的方式编码,它主要对方法调用的参数进行编码, 如方法:

double example (in short m, inout Principal p);

可表示成:

struct example_body {

short m; // leftmost in or inout parameter

Principal p; // ... to the rightmost

};

3GIOP Transport Assumptions:

主要规定在任何面向连接的网络传输层上的一些操作规则。如:Asymmetrical connection usageRequest multiplexingOverlapping requestsConnection management等。

另外,因为CORBA是基于对象的,GIOP还需定义一套Object Location的机制。

GIOP因为是一种通用协议,所以不能直接使用。在不同的网络上需要有不同的实现。目前使用最广的便是Internet上的GIOP,称为IIOPInternet Inter-ORB Protocol)。IIOP基于TCP/IP协议。IIOP消息格式定义如下:

module IIOP { // IDL extended for version 1.1

struct Version {

octet major;

octet minor;

};

struct ProfileBody_1_0 { // renamed from ProfileBody

Version iiop_version;

string host;

unsigned short port;

sequence <octet>object_key;</octet>

};

struct ProfileBody_1_1 {

Version iiop_version;

string host;

unsigned short port;

sequence <octet>object_key;</octet>

sequence <:taggedcomponent>components;<!--:taggedcomponent /-->

};

};

1.2.5 Dynamic Invocation Interface (DII) Dynamic Skeleton Interface (DSI)

动态调用接口(DII)和动态骨架接口(DSI)是用来支持客户在不知道服务器对象的接口的情况下也能调用服务器对象。

一个增加了DIIDSICORBA调用模型如下:

1.4 增加了DIIDSI的调用模型

我们在“提高篇”中再详细讲述DIIDSI

1.2.6 Object Adapter (对象适配器)

对象适配器是ORB的一部分。它主要完成对象引用的生成、维护,对象定位等功能。对象适配器有各种各样。Basic Object Adapter(BOA, 基本对象适配器)实现了对象适配器的一些核心功能。而Portable Object AdapterPOA,可移植对象适配器)则力图解决对象实现在不同厂商的ORBs下也能使用的问题。最新的ORB产品一般都支持POA

还有其他一些专有领域的对象适配器如Database Object Adapter等。

1.3 CORBA历史

CORBA是由OMGObject Management Group)负责制定和维护的一组规范。OMG成立于1989年,是一个非营利的国际性软件组织,主要致力于为分布式计算提供解决方案并制定规范。除CORBA外,OMG还制定了如UML(United Modeling Language, 统一建模语言)CWM等其他重要规范。OMG目前已有世界上760多个成员,东南大学是中国唯一的OMG成员。

CORBA1990提出并被OMG采纳以来,已历经多个版本。分别称为 CORBA 1CORBA 2CORBA 3。其中CORBA 1是对CORBA 1.x的统称,CORBA 2是对CORBA 2.x的统称。目前CORBA 3规范还在制订中,不久便可面世。

下面是CORBA版本的更新历史。

CORBA1

CORBA 1.0 90-12 提出CORBA框架

CORBA 1.1 91早期,定义了IDLORB Interface

CORBA 1.2 92-93, 修订

CORBA定义了ORB的一些基本特性,但是没有定义而ORB间的通用协议。CORBA 2主要解决这一问题。

CORBA 2

CORBA 2.0 94-12, 定义了GIOPIIOP

CORBA 2.1 97-08

CORBA 2.2 98-02, 增加了POA

CORBA 2.3 98-12

CORBA 2.3.1 99-10, 一些Change bars.

CORBA 2.4 00-10, 具备CORBA 3的雏形,包括:QoS Specification, Asynchronous Messaging, Minimum CORBA, Real-Time CORBA, CORBA Components, Notification Services, Firewall Specification等。

CORBA 2.4.1 00-11

CORBA 2.4.2 01-02

因此,可以说,CORBA 1提出ORBIDLCORBA基本概念,CORBA 2主要贡献是IIOP,而在制订中CORBA 3 则集中于CORBA Components技术及Real-time特性等。

CORBA的简要介绍就到这里。关于OMGCORBA的更多信息,可访问OMG站点:

http://www.omg.org.

下面我们开始编写第一个CORBA程序。

2.2 编写第一个CORBA程序

2.2.1 命令行方式

我们先介绍在命令行方式下的开发步骤,编写一些小型的测试程序可以使用这种方式,

因为没有必要启动庞大的JBuilder 4 后面我们再介绍在JBuilder 4集成开发环境下的使用方法。实际上两者步骤是类似的,只是方便程度不一样。

通常,开发一个CORBA应用的大致步骤如下:

1)定义 IDL

2)用IDL complier IDL编译成 Client Stub 代码和 Server Skeleton代码。

3)编写Server方的实现(Implementation)代码。

4)编写 Server

5)编写 Client

6)编译和调试。

7)运行程序。

编写Server Implementation和编写Server不是一回事。ServerClient都是带有main()函数的可执行的程序。但Server Implementation 是对interface的实现,它可以单独放在一个.java文件中,也可以和Server放在同一个文件中。

下面以一个简单的例子详细讲解各个步骤。

第一步:定义IDL

首先建立一个工作目录,这里假设为D:\mywork\simpleDemo

然后编写IDL。这个例子我们使用1.2.1 节中grid.idl,一个对二维数组操作的例子。可以使用任何文本编辑器编写,如UltraEdit等。之后保存到D:\mywork\simpleDemo下。

grid.idl定义了一个接口interface grid。其中定义两个方法get()set(),用以获取和设置数组元素值。注意属性(attribute)的定义,这是CJAVA中没有的概念(在Delphi中有这个概念),实际上它就相当于类的数据定义,但在映射到Java时被映射成方法。

第二步:编译IDL Java StubSkeleton.

打开DOS窗口,进入到D:\mywork\simpleDemo目录,在Dos命令提示符下键入:

idlj grid.idl

idlj –fserver grid.idl

注意,

我们看看idl生成的stubskeleton代码。

Stub Code包含以下文件:

grid.java 定义了接口 interface grid,

public interface grid

extends gridOperations,

org.omg.CORBA.Object,

org.omg.CORBA.portable.IDLEntity

{

}

直接由grid.idl中的interface grid 映射而来。

_gridStub.java 桩代码,定义了class _gridStub

public class _gridStub

extends org.omg.CORBA.portable.ObjectImpl

implements grid{

public void set(){…} ;

pubic int get(){..};

…}

class _gridStub中实现了客户方的set()get()等方法,它们封装了ORB的功能,截取客户的调用,执行Marshaling/Unmarshing等操作,最终得到调用结果。也就是说,在客户方声明一个grid类型的对象,实际上使用gridHelper操作得到的是一个_gridStub类型的实例,调用grid上的方法实际上是调用_gridStub上的方法。

gridHelper.java 定义 public class gridHelper{ }

帮助客户方grid对象生成一个_gridStub类型的实例,同时得到服务器对象的引用。

gridHolder.java 定义public final class gridHolder

implements org.omg.CORBA.portable.Streamable{}

当需要处理out,inout类型的参数时,需要这个类。

gridOperations.java 定义public interface gridOperations{

void set()

int get() }

这个接口实际上是Server使用的。当客户方需要使用callback功能时,也需要这个接口。

Skeleton Code则包含以下文件:

gridPOA.java 定义类abstract public class gridPOA

extends org.omg.PortableServer.Servant

implements org.omg.CORBA.portable.InvokeHandler, gridOperations

{

}

Server方的Implementation代码直接继承自这个类。

gridPOATie.java 定义类public class gridPOATie

extends simpleDemo.gridPOA

{

}

当使用代理方式而不是继承方式创建Server Object时,使用这个类。

-jpoa 参数只生成上述两个文件,实际上Skeleton Code也包含gridOperations.java,因为class gridPOA就是实现gridOperations的。

上述接口(类)的继承关系如下:

grid.idl中只定义了一个interface grid,实际上如果定义了多个interface, 那么对每个interface都会生成和上面类似的一套代码。

第三步:编写Server方的Implementation代码(即编写Servant

到现在为止,我们才开始真正编写代码。

引入了概念后,Server方的实现对象称为Servant, 编写Implementation代码实际上就是对IDL定义的每个interface,都编写一个Servant,其中要现实interface中定义的每个方法。.

这里我们将Servant类定义为class gridImpl,类名字可以自己随便取,通常都命名为xxxImpl的形式。Class gridImpl直接继承自gridPOA

D:\mywork\simpleDemo目录下创建一个gridImpl.java文件,内容如下:

package simpleDemo;

public class gridImpl extends gridPOA{

short m_height; // store the height

short m_width; // store the width

int m_array[][]; // a 2D array to hold the grid data

private int i=0;

private int j=0;

private int n=0;

public gridImpl(short width, short height)

{

m_array = new int[width][height]; // allocate the 2D array

m_height = height; // set up height

m_width = width; // set up width

}

/*

* Implementation of the method which reads the height attribute

*/

public short height()

{

return m_height;

}

/*

* Implementation of the method which reads the width attribute

*/

public short width()

{

return m_width;

}

/*

* Implementation of the set operation

*/

public void set (short x, short y, int value)

{

i++;

n++;

System.out.println ("-----µÚ "+n+" ´Îµ÷Óà Server / µÚ "+i+" ´Îµ÷Óà grid.set()----");

System.out.println ("In grid.set() x = " + x);

System.out.println ("In grid.set() y = " + y);

margin-left: 63pt

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics