Corba & IDL学习笔记

Corba简介:Common Object Request Broker Architecture, 由OMG(Object Management Group)提出并逐步完善用来完成分布式通讯的架构。是一个分布式的面向对象应用架构规范, 它 定 义 了 分 布 式 对 象 如 何 实 现 互 操 作。

Corba的核心:ORB(Object Request Broker), CORBA对象的请求者不必知道它所请求的对象是在哪里,是如何实现的,而是由ORB来负责跨平台的运作管理, CORBA是一个中间件规范并不是一个实体软件。软件开发者通过使用第三方的ORB工具或IDL语言来定义CORBA对象,实现ORB功能。简单的说ORB就是用来连接网络上的不同对象。

Corba体系结构:

Corba调用流程:

  • Idl通过idl编译器分别在客户端和服务端生成idl stub和idl skeleton类
  • 首先客户端有一个interface引用,里面是idl声明的方法,当这个interface的方法被请求的时候会指向客户端的stub类,这个类实现了客户端的interface
  • stub利用ORB机制将请求带到服务端的对象,并通过ORB连接到的服务端,向服务端的Skeleton功能发送对象引用和参数
  • skeleton通过客户端的请求找到具体实现类的方法,调用后返回。

ORB连接是建立在TCP/IP标准之上的IIOP-Internet InterORB Protocol进行通信联系,相互传送信息

Corba的服务型访问模式:

 

服务端注册具体的service到相应的Nameservice中,客户端再到相应的Nameservice中查找

OMA定义的Corba四个组成部分:

  • 对象请求代理ORB
  • 对象服务(Object Services)

ü  名录服务(Naming Service)

ü  事件服务(Event Service)

ü  生命周期服务(Life Cycle Service)

ü  关系服务(Relationship Service)

ü  事务服务(Transaction Service)

  • 公共设施(Common Facilitites):向终端用户提供一组共享服务接口
  • Business Objects

Stub流程

 

POA 工作流程:

 

Corba Ramp up开发中遇到的问题和解决方案:

遇到的错误:

1 idl中interface name与module名字最好不能相同(即使大小写不同也不行),否则如果在eclipse里面用ORB Option插件进行compile的时候会出现编译错误,如果用jdk里面的idlj编译的话  即使interface name和module name相同也没有关系

2 如果出现classNotFound的exception原因可能为

(1)最好把jacorb/lib里面所有jar加入到环境变量classpath中

(2) 如果用eclipse等ide,需要把jacorb/lib里面的jar加入到build path的libraries里面

3 jacorb ns(nameservice)启动错误:找不到或无法加载主类 Files\Java\jdk1.7.0\lib;C:\Program

在设置环境变量java_home的时候路径中最好不能有空格,否则可能出现以上错误

4 在写server端代码,initial ORB的时候传入的Properties参数中设置的NameService路径很重要

props.put(“org.omg.CORBA.ORBInitRef.NameService”, “corbaloc::16.178.110.221:9527/NameService”);

jacorb/etc/jacorb.properties文件中ORBInitRef.NameService需要配置同样的路径,否则会出现(nameservice SEVERE Could not create initial reference for “NameService”)错误

ORBInitRef.NameService=corbaloc::16.178.110.221:9527/NameService

 

未遇到需要注意的错误:

5 在jacorb/etc/jacorb.properties文件中如要配置本地路径,尽量加上ORBInitRef.NameService=file:/c:/NS_Ref 而不是ORBInitRef.NameService=c:/NS_Ref

 

 

 

IDL语言:用来完成客户端对象和服务端对象之间的接口语言。IDL里面定义了要做的事情(就是方法),Server端完成方法的具体实现,Client可以根据IDL提供的信息向服务端发出请求,并且得到请求的结果。

1 Typedef: 用来定义module里面的全局变量

  • 定义数组:typedef sequence SomeBytes; — 这个sequence里面可以存储idl里面的任意类型
  • 定长数组:typedef sequence <long, 80> SomeBytes
  • 具体类型的数组:typedef sequence <long> SomeBytes
  • 无界类型:typedef string Description; — 表示Description没有长度约束
  • 有界类型:typedef string<15> Description; — 表示长度需要小于15

2 结构类型: struct, union, enum

  • Struct

struct StructName {

char charMember;

unsigned short AnotherMember;

};

结构里面最好不用typedef

  • Enum

enum Pet {cat, dog, fish, bird, rat, horse, gerbil};

  • Union

union MyUnion switch (char) {
case ‘a’:      string aValue;
case ‘b’:      long bValue;
case ‘c’:      boolean cValue;
default:       string defValue;
};

union虽然也是一个变量的集合,但他的作用的是一次只让一个变量可用。比如参数为a的时候,aValue将可用,其他的变量不可用

3 修饰符

  • Const – 定义常量
  • Unsigned – 加上这个修饰符后表示范围为正数,比如0-2的15次方,不加则是比如2的-15到2的15次方
  • Readonly – 属性只读,有点像java的final
  • Attribute – 用来定义interface里面的属性(interface里面的属性和方法默认都是public)
  • In, out, inout:用于interface里面的方法参数修饰符

In:就是传统的要传入server的参数;

  • out:可以被修改的参数

inout: 既可以被用作输入,又可以被修改

  • Oneway:因为方法调用在服务器对象处理调用时是阻塞的,function加上oneway后,在服务器没有返回结果之前方法不会被阻塞

4 idl中不能进行方法重载

5 接口可以包含类型定义

interface Example2 {

struct Example2Struct {

string Name;

long Value;

};

// …其它定义部分

};

如果在接口外要限定Example2Struct的范围,需要加上Example2::Example2Struct

6 exception:

IDL也有现成的异常,用户可以自定义异常

异常声明 exception GetAlarmList { string reason; };

抛出异常 raises (GetAlarmList),相当于java的throws异常声明

interface BankAccount {

double getAlarms() raises

(GetAlarmList);

};

7  Module外调用,比如AModule里面需要调用BModule里面的test方法,需要BModule::test

8 继承:

interface Desendant:Ancestor {

};

Interface支持多继承,但是继承的父接口里面不能有属性或者方法重复

每个接口隐含继承了Object Interface

9 接口的相互引用:

interface Example2; // forward reference

interface Example1 {

//definitions

readonly attribute Example2 TheOtherOne;

};

interface Example2 {

//definitions

Example1 ReturnTheOtherOne ();

};

需要有提前引用(要保证引用的interface在当前interface的后面),比如Example1和Example2出现相互引用的情况,就在Example1前面定义Example2,这样Example1就在Example2的后面。

10 数据类型

  • String, wstring区别
  • Any的变量可以接受任何数据类型

wstring是宽char,Unicode编码,一般情况下一个字符占两个字节大小

string是窄char,AscII编码,一个字符占一个字节大小

11 需要注意的事项:

  • IDL变量或者方法名定义不区分大小写,比如context,CONTEXT同时使用会有冲突
  • IDL中的属性生成java类后对应getter,setter,如果这个属性是readonly, java类中将没有任何getter, setter.

12 用idl生成java类

  • idlj –fclient hello.idl – 生产客户端java类
  • idlj – fserver hello.idl – 生成服务端java类
  • idlj -fall hello.idl – 生产客户端和服务端的类(默认不加fall就是这个效果)
  • idlj -oldImplBase hello.idl – 生成老版本的java类文件(jdk1.4以前)

生成的类列表(interface名字GoodDay):

  • client端:_GoodDayStub, GoodDay, GoodDayHelper, GoodDayHolder, GoodDayOperations
  • server端:  GoodDay, GoodDayOperations, GoodDayPOA

其中两端都有GoodDay, GoodDayOperations这两个接口,而这两个接口两端代码相同,具体就是idl接口里面定义相同的方法,客户端如果是java,就可以实现真正的暴露给客户端的java接口(如果是其他语言就是c#或者c++的接口,这样就实现了语言无关性),客户端看不到实现,通过接口对服务端发出请求,然后服务端通过如客户端提供的NameService的区域里面找到相应的服务端的接口的方法然后找到具体的实现,执行后把结果返回给客户端。

生成文件的具体分析:

  • GoodDay — CORBA 规范指出这个文件必须扩展 IDLEntity,并且与 IDL 接口同名
  • GoodDayOperations – 包含idl接口定义的方法,需要被GoodDay扩展
  • GoodDayHelper – 通过这个类的narrow静态方法把从NameService取到Corbar object转为更为具体的GoodDay接口
  • GoodDayHolder –为了需要通过引用来传递参数的任意数据类型而生成的(暂时没有用到todo)
  • GoodDayStub – 从代码可以看出这个类是和服务端通信的真正的桥梁
    org.omg.CORBA.portable.OutputStream $out = _request (“hello_chinese”, true);  — 向服务端发起请求

$in = _invoke ($out);  – 得到请求结果

GoodDayPOA – 主要实现了通过服务端的一个探测功能,Stub发出请求的方法名,并且调用