IOR #
IOR用于表示一个对象引用,我们知道,当我们在客户端一个CORBA对象的时候,接触的并不是真正的对象,而是这个对象的代理(Proxy),Proxy使用这个对象的位置信息与服务器通信。那么这里有一个问题,这些信息到底些什么信息,另外,ORB使用什么样子的形式去传输这些对象的信息。答案是IOR。这里给它加上Interoperable是因为IOR是ORB Interoperability Architecture的一部分。
首先我们来看一下IOR的IDL定义:
module IOP { // IDL
// Standard Protocol Profile tag values
typedef unsigned long ProfileId
const ProfileId TAG_INTERNET_IOP = 0;
const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
struct TaggedProfile {
ProfileId tag;
sequence<octet> profile_data;
};
// an Interoperable Object Reference is a sequence of
// object-specific protocol profiles, plus a type ID.
struct IOR {
string type_id;
sequence<TaggedProfile> profiles;
};
// Standard way of representing multicomponent profiles.
// This would be encapsulated in a TaggedProfile.
typedef unsigned long ComponentId;
struct TaggedComponent {
ComponentId tag;
sequence<octet> component_data;
};
typedef sequence <TaggedComponent> MultipleComponentProfile;
};
type_id
的内容是Repository ID(这个比较难翻译,这里姑且理解成"类型"应该也不为过),用于实现类型安全,它应该是对象的 most derived(指最继承层次结构中最底部的子类)类型。在type_id为null时,它表明这是一个 Null Object Reference。profiles
,Object Reference(这里当然指IOR)至少有一TaggedProfile,每个TaggedProfile可以支持一个或者多个协议(比如IIOP),它封装了这些协议所需的用于定位对象的基本信息。一个TaggedProfile应该包含足够的信息,以使得它所支持的协议可以完成一个调用的全过程。从这里我们可以知道,TaggedProfile对应的是协议级别的信息。
TaggedProfile
tag
,OMG给每种TaggedProfile定义了一个唯一的数字,其实这是TaggedProfile的类型信息,从而决定了profile_data中的内容。对于IIOP Profile这个值是TAG_INTERNET_IOP,profile_data这个Encapsulation的内容是IIOP Profile。如果tag==TAG_MULTIPLE_COMPONENTS,那么profile_data的内容是MultipleComponentProfile。profile_data
是一个Encapsulation,如上面所说的,它的内容由tag决定,如果tag==TAG_INTERNET_IOP,profile_data这个Encapsulation的内容是IIOP Profile。如果tag==TAG_MULTIPLE_COMPONENTS,那么profile_data的内容是 MultipleComponentProfile。注意,在GIOP 1.1和1.2中,IIOPProfile也包括了一个sequence类型的字段。这里profile_data中的TaggedComponent是多个TaggedProfile之间共享的,而IIOPProfile中的sequence 是IIOPProfile自己的。
IIOPProfile
IIOPProfile是TaggedProfile的TaggedProfile实现,下面是IIOPProfile的IDL定义:
module IIOP { // IDL extended for version 1.1 and 1.2
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;
};
struct ProfileBody_1_1 {// also used for 1.2
Version iiop_version;
string host;
unsigned short port;
sequence <octet> object_key;
// Added in 1.1 unchanged for 1.2
sequence <IOP::TaggedComponent> components;
};
};
iiop_version
,iiop协议的版本信息,没有什么好说的,主版本号相同的话,那么高次版本的协议是兼容低次版的协议,同时低版本的可以尝试对高次版本的IOR进行调用。请查阅CORBA规范以获取详细信息。host
用来表示对象调用信息发往的主机名。port
用于表示对象调用信息发往的端口号。object_key
是对象的标识信息,object_key在对象中应该是唯一的。服务端通过Request Message中object_key信息来将请求委托到目标对象。components
用于表示对这个对象进行调用可能使用到的额外信息。区别于profile_data的中MultipleComponentProfile,这些信息不会在TaggedProfile之间共享。CORBA规范中定义的TaggedComponent有ORB Type,CodeSet等等。
CORBA命名服务和JNDI的之间的关系 #
CORBA 命名服务也被称做为(COSNaming,Common Object Service Naming),它提供了名字到CORBA对象之间的映射。COS Name Server(公共对象命名服务器)用于储存和查询Object Reference(对象引用)。
而JNDI(Java Naming and Directory Interface)是个更高级别的抽象,而COSNaming只是JNDI的一个具体的Service Provider(服务提供者),它提供了名字到CORBA对象的绑定;从JNDI的结构图可以看出,JNDI的服务提供者还有LDAP(根据名字定位到数据库中相对应的内容),RMI(提供RMI对象注册服务,提供了名字到RMI对象的绑定)等等。如此一来,我们便可以使用JNDI来根据名字来定位CORBA对象,绑定/解绑定对象等操作。
Java corba-test #
- 创建一个idl接口文件(HelloServer.idl)如下
interface HelloServer{
void sayHello(in string name);
};
利用idlj -fall HelloServer.idl
进行编译,会得到下面几个文件
- 创建一个HelloServerImpl实现类,实现接口中定义的功能
package com.fod.service;
public class HelloServerImpl extends HelloServerPOA{
@Override
public void sayHello(String name) {
System.out.println("Hello ," + name + ".");
}
}
- 创建服务端corba启动类HelloTestService如下
package com.fod.service;
import org.omg.CORBA.ORB;
import org.omg.CORBA.Policy;
import org.omg.PortableServer.IdAssignmentPolicyValue;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAHelper;
import org.omg.PortableServer.ThreadPolicyValue;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.Properties;
public class HelloTestService {
public static void main(String[] args) {
// 生成一个ORB,并初始化,这个和Server端一样
Properties props = System.getProperties();
//配置发布端口和ip
props.put("org.omg.CORBA.ORBInitialPort", "1050");
props.put("org.omg.CORBA.ORBInitialHost", "192.168.0.106");
System.out.println("ORB initialised\n");
try {
// Initialize the ORB.
ORB orb = ORB.init(args, props);
// get a reference to the root POA
org.omg.CORBA.Object obj = orb.resolve_initial_references("RootPOA");
POA poaRoot = POAHelper.narrow(obj);
// Create policies for our persistent POA
Policy[] policies = {
// poaRoot.create_lifespan_policy(LifespanPolicyValue.PERSISTENT),
poaRoot.create_id_assignment_policy(IdAssignmentPolicyValue.USER_ID),
poaRoot.create_thread_policy(ThreadPolicyValue.ORB_CTRL_MODEL)
};
// Create myPOA with the right policies
POA poa = poaRoot.create_POA("HelloServerPOA", poaRoot.the_POAManager(), policies);
// Create the servant
HelloServerImpl servant = new HelloServerImpl();
// Activate the servant with the ID on myPOA
byte[] objectId = "AnyObjectID".getBytes();
poa.activate_object_with_id(objectId, servant);
// Activate the POA manager
poaRoot.the_POAManager().activate();
// Get a reference to the servant and write it down.
obj = poa.servant_to_reference(servant);
PrintWriter ps = new PrintWriter(new FileOutputStream(new File("server.ior")));
ps.println(orb.object_to_string(obj));
ps.close();
System.out.println("CORBA Server ready...");
// Wait for incoming requests
orb.run();
}
catch(Exception ex) {
ex.printStackTrace();
}
}
}
- 创建corba客户端操作类如下
package com.fod.service;
import java.io.FileReader;
import java.io.LineNumberReader;
import java.util.Properties;
class HelloClientImpl {
private HelloServer target = null;
private org.omg.CORBA.ORB orb = null;
/**
* Constructor for HelloClientImpl
*
*/
public HelloClientImpl() throws Exception {
initORB(null);
}
/**
* Constructor for HelloClientImpl
* @see java.lang.Object#Object()
*/
public HelloClientImpl(String[] args) throws Exception {
initORB(args);
}
/**
* Initialize ORB.
*
* @param args
*/
public void initORB(String[] args) throws Exception {
//设置远程调用ip和端口
Properties props = System.getProperties();
props.put("org.omg.CORBA.ORBInitialPort", "1050");
props.put("org.omg.CORBA.ORBInitialHost", "192.168.0.106");
// Initialize the ORB
orb = org.omg.CORBA.ORB.init((String[])args, props);
// ---- Uncomment below to enable Naming Service access. ----
// LineNumberReader input = new LineNumberReader(new FileReader("server.ior"));
// String ior = input.readLine();
//此处的ior串是你环境上server.ior文件中的一串字符
org.omg.CORBA.Object obj = orb.string_to_object("IOR:000000000000001449444c3a48656c6c6f5365727665723a312e3000000000010000000000000096000102000000000a3132372e302e312e3100b49100000048afabcb00000000206fe9875200000001000000000000000200000008526f6f74504f41000000000f48656c6c6f536572766572504f4100000000000b416e794f626a656374494414000000020000000100000020000000000001000100000002050100010001002000010109000000010001010000000026000000020002");
target = HelloServerHelper.narrow(obj);
}
/**
* Obtain ORB Interface.
*
* @return
*/
public HelloServer getORBInterface() {
return target;
}
/**
* Shutdown ORB.
*/
public void shutdown() {
orb.shutdown(true);
}
/**
* Test driver for HelloClientImpl.
* @param args
*/
public static void main(String[] args) {
try {
HelloClientImpl test = new HelloClientImpl();
test.getORBInterface().sayHello("lifa");
//停止
test.shutdown();
}catch(Exception ex) {
ex.printStackTrace();
}
}
}
- 启动服务端,然后启动客户端,就会看到服务端控制台打印了
Hello, lifa