Skip to main content

CORBA-IOR

·606 words·3 mins
WFUing
Author
WFUing
A graduate who loves coding.
Table of Contents

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对象,绑定/解绑定对象等操作。

JNDI结构

Java corba-test
#

  1. 创建一个idl接口文件(HelloServer.idl)如下
interface HelloServer{
  void sayHello(in string name);
};

利用idlj -fall HelloServer.idl进行编译,会得到下面几个文件

  1. 创建一个HelloServerImpl实现类,实现接口中定义的功能
package com.fod.service;

public class HelloServerImpl extends HelloServerPOA{
    @Override
    public void sayHello(String name) {
        System.out.println("Hello ," + name + ".");

    }
}
  1. 创建服务端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();
        }
    }
}
  1. 创建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();
        }
    }
}
  1. 启动服务端,然后启动客户端,就会看到服务端控制台打印了 Hello, lifa

Resources
#


💬评论