<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    kapok

    垃圾桶,嘿嘿,我藏的這么深你們還能找到啊,真牛!

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      455 隨筆 :: 0 文章 :: 76 評(píng)論 :: 0 Trackbacks

    http://www.huihoo.com/corba/java/rmi_corba.html

    使用RMI和CORBA進(jìn)行分布式j(luò)ava程序設(shè)計(jì)


    (by huihoo.com lizhi) 分布式程序設(shè)計(jì)討論>>>

    英文原文:http://developer.java.sun.com/developer/technicalArticles/RMI/rmi_corba/

    RMI和corba是兩種最重要和使用最廣泛的分布式對(duì)象系統(tǒng)。 每種都有它的長(zhǎng)處和短處。這兩種系統(tǒng)都在從電子商務(wù)到衛(wèi)生保健等不同的行業(yè)成功的使用。在項(xiàng)目中使用這兩種分布機(jī)制中的任何一種都是一項(xiàng)很困難的任務(wù)。本文介紹了RMI和corba的機(jī)理和最主要的是顯示了如何開(kāi)發(fā)一個(gè)有用的程序(一個(gè)從遠(yuǎn)程站點(diǎn)下載文件的程序)。于是有以下內(nèi)容:

    • 一個(gè)分布式系統(tǒng)的簡(jiǎn)介
    • 一個(gè)RMI和corba的簡(jiǎn)介
    • 讓你體驗(yàn)開(kāi)發(fā)一個(gè)RMI和corba程序的滋味。
    • 說(shuō)明如何使用RMI和corba從遠(yuǎn)程機(jī)器交換文件
    • 提供一個(gè)RMI和Corba的比較。

    客戶(hù)/服務(wù)端模式

    客戶(hù)/服務(wù)模式是一個(gè)分布式計(jì)算應(yīng)用。它通過(guò)使用一個(gè)應(yīng)用程序(客戶(hù))和另一個(gè)程序(服務(wù)端)交換數(shù)據(jù)。在這樣的一個(gè)例子里面客戶(hù)端和服務(wù)端一般使用同樣的語(yǔ)言來(lái)編寫(xiě),使用相同的協(xié)議來(lái)相互通信。
    在客戶(hù)/服務(wù)模式應(yīng)用到各種各樣的地方的過(guò)程中,使用低層次的socket來(lái)開(kāi)發(fā)是很典型的。使用socket來(lái)開(kāi)發(fā)客戶(hù)/服務(wù)端模式意味著我們必須自己設(shè)計(jì)一種協(xié)議,該協(xié)議包含客戶(hù)端和服務(wù)端都統(tǒng)一的命令集 ,使得客戶(hù)端和服務(wù)端能夠通過(guò)這個(gè)協(xié)議來(lái)通信。例如:HTTP協(xié)議提供了一個(gè)get的方法。所有的web服務(wù)器軟件都集成了該功能,而所有的瀏覽器軟件都能夠使用該功能來(lái)獲得資料。

    分布式對(duì)象模式

    分布式對(duì)象系統(tǒng)是一個(gè)對(duì)象集合,通過(guò)定義很完善的統(tǒng)一的接口來(lái)分隔開(kāi)的要求服務(wù)(客戶(hù)端)和功能服務(wù)(服務(wù)端)。換句話說(shuō)客戶(hù)端和公共服務(wù)的提供分隔開(kāi),這些服務(wù)包括數(shù)據(jù)表現(xiàn)和執(zhí)行的代碼。這是一個(gè)分辨分布式對(duì)象模式和客戶(hù)/服務(wù)模式的主要不同。

    在分布式對(duì)象模式里,客戶(hù)端發(fā)送一個(gè)消息到一個(gè)對(duì)象,由這個(gè)對(duì)象解釋這個(gè)消息然后決定應(yīng)該由什么服務(wù)來(lái)完成。這個(gè)服務(wù),方法或選擇的完成可能是被一個(gè)對(duì)象或是被一個(gè)broker。RMI和corba就是這種模式的例子。

    RMI

    RMI是一個(gè)分布式對(duì)象模式。它使得使用java開(kāi)發(fā)分布式程序更加容易。由于不需要設(shè)計(jì)協(xié)議(這基本是一個(gè)錯(cuò)誤的任務(wù)) 使得使用RMI開(kāi)發(fā)分布式程序比使用socket更加容易。在RMI里面設(shè)計(jì)者就象在調(diào)用一個(gè)本地的類(lèi)的方法一樣,而實(shí)際上是在調(diào)用的時(shí)候相應(yīng)的參數(shù)被發(fā)送到遠(yuǎn)端的對(duì)象和然后被解釋。最后結(jié)果返回給調(diào)用者。

    一個(gè) RMI應(yīng)用的流程

    使用 RMI開(kāi)發(fā)一個(gè)分布式應(yīng)用包括如下幾個(gè)步驟
    1)定義一個(gè)遠(yuǎn)端的接口
    2)實(shí)現(xiàn)這個(gè)遠(yuǎn)端的接口
    3)開(kāi)發(fā)一個(gè)服務(wù)端
    4)開(kāi)發(fā)一個(gè)客戶(hù)端
    5)生成Stubs 和Skeletons,運(yùn)行RMI注冊(cè)器,服務(wù)端 和客戶(hù)端
    我們現(xiàn)在通過(guò)開(kāi)發(fā)一個(gè)文件交換程序來(lái)解釋這些步驟

    例子:文件交換程序

    這個(gè)應(yīng)用允許客戶(hù)端從服務(wù)端交換(或下載)所有類(lèi)型的文件。第一步是定義一個(gè)遠(yuǎn)程的接口,這個(gè)接口指定了的簽名方法將被服務(wù)端提供和被客戶(hù)端調(diào)用。

    定義一個(gè)遠(yuǎn)程接口

    這個(gè)程序的遠(yuǎn)程接口在代碼例子1中列出,接口FileInterface提供一個(gè)downloadFile這個(gè)帶一個(gè)字符竄(文件名)變量的的方法,然后返回以一個(gè)字符竄序列的形式的相應(yīng)文件數(shù)據(jù)。

    代碼例子1: FileInterface.java

    import java.rmi.Remote;
    import java.rmi.RemoteException;
    
    public interface FileInterface extends Remote {
       public byte[] downloadFile(String fileName) throws
       RemoteException;
    }
    

    注意接口FileInterface的如下特征:

    • 它必須定義成public,這是為了讓客戶(hù)端能夠通過(guò)調(diào)用遠(yuǎn)程接口來(lái)間接調(diào)用遠(yuǎn)程的對(duì)象。
    • 必須使用從Remote接口擴(kuò)展過(guò)來(lái),這是創(chuàng)建一個(gè)遠(yuǎn)程的對(duì)象的需要。
    • 每個(gè)接口方法中必須拋出java.rmi.RemoteException錯(cuò)誤。

    實(shí)現(xiàn)遠(yuǎn)程的接口

    下一步是實(shí)現(xiàn)遠(yuǎn)程的接口FileInterface。實(shí)現(xiàn)的例子在代碼例子 2中列出。類(lèi)FileImpl從UnicastRemoteObject擴(kuò)展來(lái)。這顯示出FileImpl類(lèi)是用來(lái)創(chuàng)建一個(gè)單獨(dú)的,不能復(fù)制的,遠(yuǎn)程的對(duì)象,
    這個(gè)對(duì)象使用RMI 的默認(rèn)的基于TCP的通信方式。

    代碼例子 2: FileImpl.java

    import java.io.*;
    import java.rmi.*;
    import java.rmi.server.UnicastRemoteObject;
    
    public class FileImpl extends UnicastRemoteObject
      implements FileInterface {
    
       private String name;
    
       public FileImpl(String s) throws RemoteException{
          super();
          name = s;
       }
    
       public byte[] downloadFile(String fileName){
          try {
             File file = new File(fileName);
             byte buffer[] = new byte[(int)file.length()];
             BufferedInputStream input = new
          BufferedInputStream(new FileInputStream(fileName));
             input.read(buffer,0,buffer.length);
             input.close();
             return(buffer);
          } catch(Exception e){
             System.out.println("FileImpl: "+e.getMessage());
             e.printStackTrace();
             return(null);
          }
       }
    }
    

    編寫(xiě)服務(wù)端
    第3步是實(shí)現(xiàn)一個(gè)服務(wù)端。有3件事服務(wù)端需要去做:
    1)創(chuàng)建一個(gè)RMISecurityManager實(shí)例,然后安裝它。
    2)創(chuàng)建一個(gè)遠(yuǎn)程對(duì)象的實(shí)例(這個(gè)例子中是FileImpl )
    3)使用RMI注冊(cè)工具來(lái)注冊(cè)這個(gè)對(duì)象。
    代碼例子 3中顯示了如何操作的。
    代碼例子 3: FileServer.java

    import java.io.*;
    import java.rmi.*;
    
    public class FileServer {
       public static void main(String argv[]) {
          if(System.getSecurityManager() == null) {
             System.setSecurityManager(new RMISecurityManager());
          }
          try {
             FileInterface fi = new FileImpl("FileServer");
             Naming.rebind("http://127.0.0.1/FileServer", fi);
          } catch(Exception e) {
             System.out.println("FileServer: "+e.getMessage());
             e.printStackTrace();
          }
       }
    }
    

    聲明Naming.rebind("http://127.0.0.1/FileServer", fi) 中假定了RMI注冊(cè)工具(RMI registry )使用1099端口并在運(yùn)行中。如果你在其他的端口運(yùn)行了RMI注冊(cè)工具,你必須在這個(gè)聲明中定義。例如如果RMI注冊(cè)工具在4500端口運(yùn)行。你的聲明要變成
    Naming.rebind("http://127.0.0.1:4500/FileServer", fi)
    另外我們已經(jīng)同時(shí)假定了我們的服務(wù)端和RMI注冊(cè)工具是運(yùn)行在同一臺(tái)機(jī)器上的。如果不是的話你要修改rebind方法中的地址。

    編寫(xiě)客戶(hù)端 下一步是編寫(xiě)一個(gè)客戶(hù)端,客戶(hù)端可以遠(yuǎn)程調(diào)用遠(yuǎn)程接口(FileInterface)中說(shuō)明的任何一個(gè)方法。無(wú)論如何實(shí)現(xiàn),客戶(hù)端必須先從RMI注冊(cè)工具獲得一個(gè)遠(yuǎn)程對(duì)象的引用。當(dāng)引用獲得后方法downloadFile 被調(diào)用。客戶(hù)端的例子在代碼例子4中,執(zhí)行過(guò)程中客戶(hù)端從命令行中獲得兩個(gè)參數(shù),第一個(gè)是要下載的文件名,第二個(gè)是要下載的機(jī)器的地址。對(duì)應(yīng)地址的機(jī)器上運(yùn)行服務(wù)端。

    代碼例子 4: FileClient.java

    import java.io.*; 
    import java.rmi.*;
    
    public class FileClient{
       public static void main(String argv[]) {
          if(argv.length != 2) {
            System.out.println("Usage: java FileClient fileName machineName");
            System.exit(0);
          }
          try {
             String name = "http://" + argv[1] + "/FileServer";
             FileInterface fi = (FileInterface) Naming.lookup(name);
             byte[] filedata = fi.downloadFile(argv[0]);
             File file = new File(argv[0]);
             BufferedOutputStream output = new
               BufferedOutputStream(new FileOutputStream(file.getName()));
             output.write(filedata,0,filedata.length);
             output.flush();
             output.close();
          } catch(Exception e) {
             System.err.println("FileServer exception: "+ e.getMessage());
             e.printStackTrace();
          }
       }
    }
    

    運(yùn)行程序
    為了運(yùn)行程序我們必須生成stubs 和 skeletons,為了生成stubs 和 skeletons,我們使用rmic來(lái)編譯:
    prompt> rmic FileImpl
    將會(huì)生成兩個(gè)文件FileImpl_Stub.class和 FileImpl_Skel.class. stub是客戶(hù)端的代理而skeleton是服務(wù)端的框架。
    下一步是編譯服務(wù)端和客戶(hù)端。使用javac來(lái)編譯。注意如果服務(wù)端和客戶(hù)端在兩個(gè)不同的機(jī)器,為了編譯客戶(hù)端你必須復(fù)制一個(gè)FileInterface接口。
    最后,到你運(yùn)行RMI注冊(cè)工具和運(yùn)行服務(wù)端和客戶(hù)端的時(shí)候了。使用rmiregistry 或者 start rmiregistry 命令來(lái)運(yùn)行RMI注冊(cè)工具到window系統(tǒng)的默認(rèn)的端口上,要運(yùn)行RMI注冊(cè)工具在一個(gè)其他的端口的話使用端口參數(shù)。
    prompt> rmiregistry portNumber
    RMI注冊(cè)工具運(yùn)行之后,你要運(yùn)行服務(wù)FileServer,因?yàn)镽MI的安全機(jī)制將在服務(wù)端發(fā)生作用,所以你必須增加一條安全策略。以下是對(duì)應(yīng)安全策略的例子
    grant {
    permission java.security.AllPermission "", "";
    };
    注意:這是一條最簡(jiǎn)單的安全策略,它允許任何人做任何事,對(duì)于你的更加關(guān)鍵性的應(yīng)用,你必須指定更加詳細(xì)安全策略。
    現(xiàn)在為了運(yùn)行服務(wù)端,你需要除客戶(hù)類(lèi)(FileClient.class)之外的所有的類(lèi)文件。確認(rèn)安全策略在policy.txt文件之后,使用如下命令來(lái)運(yùn)行服務(wù)器。
    prompt> java -Djava.security.policy=policy.txt FileServer
    為了在其他的機(jī)器運(yùn)行客戶(hù)端程序你需要一個(gè)遠(yuǎn)程接口(FileInterface.class) 和一個(gè)stub(FileImpl_Stub.class)。 使用如下命令運(yùn)行客戶(hù)端
    prompt> java FileClient fileName machineName
    這里fileName是要下載的文件名,machineName 是要下載的文件所在的機(jī)器(也是服務(wù)端所在的機(jī)器)
    如果所有都可以了話,當(dāng)客戶(hù)端運(yùn)行后,這個(gè)文件將下載到本地。


    我們提到如果要運(yùn)行客戶(hù)端,我們需要遠(yuǎn)程接口和stub,另外一個(gè)更好的方法是使用RMI動(dòng)態(tài)類(lèi)加載,這個(gè)方法使得你不必要復(fù)制遠(yuǎn)程接口和stub。取而代之的是,它們能夠在一個(gè)共同的目錄里面被客戶(hù)端和服務(wù)端查找到。為了做到這個(gè)你必須使用以下命令來(lái)運(yùn)行客戶(hù)端。
    使用如下命令
    java -Djava.rmi.server.codebase=http://hostname/locationOfClasses FileClient fileName machineName.
    更多的信息看這里Dynamic Code Loading using RMI.


    CORBA

    CORBA(The Common Object Request Broker Architecture:通用對(duì)象請(qǐng)求代理結(jié)構(gòu))是對(duì)象管理組織(ORG)在分布式對(duì)象項(xiàng)目方面資助的一個(gè)工業(yè)標(biāo)準(zhǔn)。CORBA只是一個(gè)標(biāo)準(zhǔn),一個(gè)CORBA服務(wù)以O(shè)RB(Object Request Broker對(duì)象要求代理)的形式來(lái)運(yùn)行,市場(chǎng)上有很多可用的CORBA ORB服務(wù)軟件例如VisiBroker, ORBIX, 和其他一些ORB軟件。JavaIDL 是其中的一個(gè),它是jdk1.3或jdk1.3以上版本的一個(gè)核心開(kāi)發(fā)包。
    CORBA的設(shè)計(jì)是獨(dú)立于平臺(tái)和語(yǔ)言的,因此CORBA可以在任何平臺(tái)上運(yùn)行,可以定位在網(wǎng)絡(luò)的任何地方,能夠使用任何有IDL(Interface Definition Language )映射的語(yǔ)言。
    和RMI相類(lèi)似,CORBA對(duì)象使用接口來(lái)描述,然而接口在CORBA中是定義在IDL中的。IDL很類(lèi)似于C++,但是IDL不是編程語(yǔ)言,更多的關(guān)于CORBA的介紹在這里有Distributed Programming with Java: Chapter 11 (Overview of CORBA).

    CROBA程序的編寫(xiě)過(guò)程
    開(kāi)發(fā)CORBA有很多復(fù)雜的步驟,如下
    1.定義一個(gè)IDL
    2.把IDL接口映射到j(luò)ava
    3.開(kāi)發(fā)server端
    4.開(kāi)發(fā)client端
    5.運(yùn)行名字服務(wù),服務(wù)端 和客戶(hù)端

    我們現(xiàn)在一步步的解釋一個(gè)基corba的文件交換程序的開(kāi)發(fā),這有點(diǎn)類(lèi)似于我們上面講的RMI程序的開(kāi)發(fā),我們這里使用JavaIDL(一個(gè)jdk1.3的核心開(kāi)發(fā)包).

    定義接口

    當(dāng)你定義一個(gè)corba的接口時(shí),考慮一下服務(wù)要支持的操作,在這個(gè)程序里面客戶(hù)端將包含一個(gè)下載文件的方法。代碼例子5顯示了一個(gè)FileInterface接口,Data是一個(gè)用typedef關(guān)鍵字引入的新的類(lèi)型描述。sequence 在IDL中除了不能定義固定大小外其他都類(lèi)似于數(shù)組,octet是一個(gè)8字節(jié)的量,相當(dāng)于java中的byte。downloadFile 方法中的參數(shù)是一個(gè)string類(lèi)型并被定義成in 類(lèi)型。IDL定義了3中傳輸模式:in(用來(lái)接收客戶(hù)端到服務(wù)端的輸入),out(用來(lái)接收服務(wù)端到客戶(hù)端的輸出)和inout(同時(shí)用來(lái)輸入和輸出)。

    代碼例子 5: FileInterface.idl

    interface FileInterface {
       typedef sequence<octet> Data;
       Data downloadFile(in string fileName);
    };
    

    一旦你定義了一個(gè)IDL接口,你就要開(kāi)始編譯它。JDK1.3+包含了一個(gè)idlj 編譯器,它可以用來(lái)映射IDL到j(luò)ava的聲明。
    idlj 可以通過(guò)不同的命令產(chǎn)生不同的輸出如客戶(hù)端的stubs,服務(wù)端的skeletons。
    -f<side> 參數(shù)用來(lái)指定產(chǎn)生什么。side是如下的client, server, 或 all 參數(shù)分別用來(lái)表示客戶(hù)端的stubs 和服務(wù)端的 skeletons。在這個(gè)例子里由于服務(wù)端和客戶(hù)端在兩個(gè)不同的機(jī)器上,所以我們?cè)诳蛻?hù)端上使用-fclient 在服務(wù)端上使用-fserver 。
    現(xiàn)在讓我們編譯FileInterface.idl 來(lái)產(chǎn)生服務(wù)端的skeletons,使用如下命令
    prompt> idlj -fserver FileInterface.idl
    執(zhí)行接口
    現(xiàn)在我們提供一個(gè)對(duì)downloadFile方法的執(zhí)行。這個(gè)執(zhí)行就像一個(gè)仆人,你可以從例子6中看出 FileServant 類(lèi)從_FileInterfaceImplBase 類(lèi)擴(kuò)展過(guò)來(lái)。從這個(gè)類(lèi)可以看出這個(gè)仆人是一個(gè)corba對(duì)象
    例子6代碼: FileServant.java

    import java.io.*; 
    
    public class FileServant extends _FileInterfaceImplBase {
       public byte[] downloadFile(String fileName){
          File file = new File(fileName);
          byte buffer[] = new byte[(int)file.length()];
          try {
             BufferedInputStream input = new
               BufferedInputStream(new FileInputStream(fileName));
             input.read(buffer,0,buffer.length);
             input.close();
          } catch(Exception e) {
             System.out.println("FileServant Error: "+e.getMessage());
             e.printStackTrace();
          }
          return(buffer); 
       }
    }
    

    開(kāi)發(fā)服務(wù)端
    下一步是編寫(xiě)corba服務(wù)端。在例子7中實(shí)現(xiàn)了一個(gè)corba服務(wù)端的類(lèi) FileServer。它通過(guò)以下的步驟來(lái)實(shí)現(xiàn)。
    1)定義一個(gè)orb
    2)創(chuàng)建一個(gè)FileServant對(duì)象
    3)登記到corba命名服務(wù)中(COS Naming)
    4)打印狀態(tài)消息
    5)等待客戶(hù)端請(qǐng)求
    例子7代碼: FileServer.java

    import java.io.*;
    import org.omg.CosNaming.*;
    import org.omg.CosNaming.NamingContextPackage.*;
    import org.omg.CORBA.*;
    
    public class FileServer {
       public static void main(String args[]) {
          try{
             // create and initialize the ORB
             ORB orb = ORB.init(args, null);
             // create the servant and register it with the ORB
             FileServant fileRef = new FileServant();
             orb.connect(fileRef);
             // get the root naming context
             org.omg.CORBA.Object objRef =
                orb.resolve_initial_references("NameService");
             NamingContext ncRef = NamingContextHelper.narrow(objRef);
             // Bind the object reference in naming
             NameComponent nc = new NameComponent("FileTransfer", " ");
             NameComponent path[] = {nc};
             ncRef.rebind(path, fileRef);
             System.out.println("Server started....");
             // Wait for invocations from clients
             java.lang.Object sync = new java.lang.Object();
             synchronized(sync){
                sync.wait();
             }
          } catch(Exception e) {
             System.err.println("ERROR: " + e.getMessage());
             e.printStackTrace(System.out);
          }
       }
    }
    

    一旦FileServer 獲得一個(gè)orb, 它能夠登記corba服務(wù)。它使用由omg建議的由Java IDL 實(shí)現(xiàn)的corba名字服務(wù)(COS Naming Service )來(lái)登記。它是目錄服務(wù)中從根節(jié)點(diǎn)開(kāi)始的一個(gè)目錄節(jié)點(diǎn)。這是一個(gè)普通的corba對(duì)象。可以當(dāng)成NamingContext對(duì)象來(lái)使用。它必須能夠被narrowed down (換句話說(shuō)是分級(jí)(casted))
    到相應(yīng)的類(lèi)型。這是使用一個(gè)聲明來(lái)實(shí)現(xiàn)的。
    NamingContext ncRef = NamingContextHelper.narrow(objRef);
    ncRef對(duì)象現(xiàn)在是org.omg.CosNaming.NamingContext對(duì)象。你可以使用它來(lái)登記一個(gè)corba服務(wù)。 rebind 調(diào)用方法可以實(shí)現(xiàn)。
    開(kāi)發(fā)客戶(hù)端
    下一步是開(kāi)發(fā)一個(gè)客戶(hù)端,在例子8里面實(shí)現(xiàn)了,一旦得到了一個(gè)到名字服務(wù)的引用,它就能夠被用來(lái)進(jìn)入名字服務(wù)和能夠用來(lái)查找一些服務(wù)(例如這里查找的是FileTransfer 服務(wù))當(dāng)FileTransfer 服務(wù)被找到的時(shí)候,downloadFile 方法將被調(diào)用。
    例子8代碼:FileClient

    import java.io.*;
    import java.util.*;
    import org.omg.CosNaming.*;
    import org.omg.CORBA.*;
    
    public class FileClient {
       public static void main(String argv[]) {
          try {
             // create and initialize the ORB
             ORB orb = ORB.init(argv, null);
             // get the root naming context
             org.omg.CORBA.Object objRef =
                orb.resolve_initial_references("NameService");
             NamingContext ncRef = NamingContextHelper.narrow(objRef);
             NameComponent nc = new NameComponent("FileTransfer", " ");      
             // Resolve the object reference in naming
             NameComponent path[] = {nc};
             FileInterfaceOperations fileRef =
                FileInterfaceHelper.narrow(ncRef.resolve(path));
    
             if(argv.length < 1) {
                System.out.println("Usage: java FileClient filename");
             }
    
             // save the file
             File file = new File(argv[0]);
             byte data[] = fileRef.downloadFile(argv[0]);
             BufferedOutputStream output = new
               BufferedOutputStream(new FileOutputStream(argv[0]));
             output.write(data, 0, data.length);
             output.flush();
             output.close();
          } catch(Exception e) {
             System.out.println("FileClient Error: " + e.getMessage());
             e.printStackTrace();
          }
       }
    }
    

    運(yùn)行應(yīng)用

    最后一步是運(yùn)行這個(gè)應(yīng)用(萬(wàn)里長(zhǎng)征最后一步 哈哈高興吧)。這里有幾個(gè)小的步驟。
    1)運(yùn)行CORBA名字服務(wù)。這里可以使用tnameserv命令。它默認(rèn)運(yùn)行在900端口。你還可以改變端口號(hào)
    例如使用如下命令讓你的服務(wù)運(yùn)行在2500端口。
    prompt> tnameserv -ORBinitialPort 2500
    2)運(yùn)行服務(wù)端
    如果CORBA名字服務(wù)在默認(rèn)的端口的時(shí)候使用如下命令。
    prompt> java FileServer
    如果你的CORBA名字服務(wù)在自己定義的端口如2500,使用如下命令,這里使用-ORBInitialPort 來(lái)定義端口
    prompt> java FileServer -ORBInitialPort 2500

    3)創(chuàng)建客戶(hù)端的Stubs。我們?cè)谶\(yùn)行客戶(hù)端之前我們必須創(chuàng)建一個(gè)Stubs。首先我們要得到一個(gè)FileInterface.idl 的復(fù)制,然后用如下命令編譯。
    prompt> idlj -fclient FileInterface.idl
    4)運(yùn)行客戶(hù)端。現(xiàn)在你可以運(yùn)行客戶(hù)端了,以下命令是假定corba名字服務(wù)在2500端口處監(jiān)聽(tīng)。
    prompt> java FileClient hello.txt -ORBInitialPort 2500
    這樣hello.txt文件可以從服務(wù)端下載下來(lái)了。

    另外的,有些選項(xiàng)通過(guò)代碼定義的屬性來(lái)定義。比如代替初始化orb的代碼如下
    ORB orb = ORB.init(argv, null);
    它能修改一些參數(shù),使得orb在2500端口提供和corba服務(wù)的名字叫g(shù)osling。例子如下。
    Properties props = new Properties();
    props.put("org.omg.CORBA.ORBInitialHost", "gosling");
    props.put("orb.omg.CORBA.ORBInitialPort", "2500");
    ORB orb = ORB.init(args, props);

    練習(xí)

    在這個(gè)文件交換程序里面,客戶(hù)端(不管是corba 還是rmi)需要知道將要下載的文件名,可是沒(méi)有方法提供列出可以用到的文件。作為一個(gè)練習(xí),你可能想加入一些方法來(lái)比如提供列出可以用到的文件名來(lái)提高這個(gè)應(yīng)用程序的可使用性。另外,你可能想開(kāi)發(fā)一個(gè)基于圖形的客戶(hù)端來(lái)代替字符客戶(hù)端。當(dāng)客戶(hù)端運(yùn)行的時(shí)候它調(diào)用一個(gè)在服務(wù)端的方法來(lái)得到文件列表然后彈出一個(gè)菜單來(lái)顯示所有用戶(hù)可以選擇下載的文件。用戶(hù)可以選擇一個(gè)或多個(gè)文件來(lái)下載. 如下 圖1

    figure 1

    Figure 1: GUI-based File Transfer Client

    CORBA vs. RMI

    從編碼來(lái)看,很明顯,RMI對(duì)于java 開(kāi)發(fā)人員來(lái)說(shuō)很容易使用。他們不需要了解IDL語(yǔ)言 Interface Definition Language 。
    然而一般來(lái)說(shuō)corba和RMI在如下方面各不相同。
    (1)corba的interfaces(接口)使用IDL來(lái)定義,RMI 接口使用java來(lái)定義。RMI-IIOP允許所有的interfaces(接口)使用java來(lái)編寫(xiě)。
    (2)COrba提供in 和 out參數(shù)。同時(shí)RMI不提供,這是因?yàn)楸镜貙?duì)象能夠復(fù)制。
    (3)CORBA使用一種特殊的語(yǔ)言來(lái)設(shè)計(jì)interfaces(接口),這意味著一些對(duì)象可以使用java來(lái)編寫(xiě) 而另外一些類(lèi)可以使用 另外的語(yǔ)言例如C++來(lái)編寫(xiě)它們能夠協(xié)同的工作。因此corba是一種連接各種孤立語(yǔ)言的理想機(jī)制。而RMI只是對(duì)所有java編寫(xiě)的對(duì)象設(shè)計(jì)的。但是RMI-IIOP提供協(xié)同工作的能力。
    (4)CORBA對(duì)象不被自動(dòng)回收.就像我們以上提到的,corba是一種獨(dú)立的特殊語(yǔ)言,另外一些語(yǔ)言(例如C++)不提供垃圾收集。這可能會(huì)造成不利的情況,因?yàn)閏orba對(duì)象一旦創(chuàng)建,它將一直存在直到你殺掉它,而決定一個(gè)對(duì)象什么時(shí)候?qū)⒈粴⒌舨皇且患芎?jiǎn)單的工作。而RMI對(duì)象能夠自動(dòng)的被收集。

    結(jié)論

    可以使用RMI和JavaIDL(一個(gè)corba的實(shí)現(xiàn))開(kāi)發(fā)一個(gè)基于分布式對(duì)象的java應(yīng)用程序。使用這兩種技術(shù)從第一步到定義一個(gè)對(duì)象的接口都是很相似的。
    然而和RMI把對(duì)象接口(interfaces)定義在java中不同的是,Corba的對(duì)象接口(interfaces)定義在IDL(Interface Definition Language )中,這樣增加了其他層的復(fù)雜性,使得需要開(kāi)發(fā)人員需要了解IDL和IDL到j(luò)ava 的映射。
    在這兩種機(jī)制之間做選擇依靠手頭的項(xiàng)目和項(xiàng)目的要求。我希望本文能夠給你提供足夠的信息來(lái)開(kāi)始開(kāi)發(fā)一個(gè)基于對(duì)象分布式應(yīng)用程序和給你提供足夠的指導(dǎo)
    來(lái)選擇一個(gè)分布機(jī)制。

    更多的相關(guān)參考:

    - RMI
    - CORBA Specification (OMG)
    - JavaIDL
    - Distributed Programming with Java book (Chapter 11: Overview of CORBA)
    - CORBA Server and Servlet Client
    - RMI-IIOP

    關(guān)于作者


    Qusay H. Mahmoud 專(zhuān)門(mén)提供關(guān)于 Java 的咨詢(xún)和培訓(xùn)。他發(fā)表了許多關(guān)于java的文章 , 它還是
    <<Distributed Programming with Java >> (1999)和 <<Learning Wireless Java>>(2000)的作者。

    posted on 2005-06-15 11:51 笨笨 閱讀(560) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): J2EEALL
    主站蜘蛛池模板: 亚洲人成网7777777国产| 无码一区二区三区免费| 精品国产日韩亚洲一区91| 亚洲 欧洲 日韩 综合在线| 亚洲免费人成视频观看| 亚洲欧洲国产精品久久| 亚洲美女激情视频| 91嫩草亚洲精品| 亚洲午夜电影一区二区三区| 亚洲一区二区三区久久| 国产成人精品日本亚洲专一区| 国产精品亚洲专区在线观看| 亚洲三级在线观看| 亚洲heyzo专区无码综合| 最新亚洲人成无码网站| 一本一道dvd在线观看免费视频 | 在线观看免费亚洲| 国产成人在线观看免费网站| 免费人成在线观看播放国产| 亚洲天堂在线视频| 亚洲综合图色40p| 亚洲精品私拍国产福利在线| 亚洲国产精品综合一区在线| 亚洲人成777在线播放| 亚洲国产精品99久久久久久| 免费观看亚洲人成网站| 久久免费视频一区| 98精品全国免费观看视频| 国产成人精品免费视频动漫| 少妇高潮太爽了在线观看免费| 卡一卡二卡三在线入口免费| 无码不卡亚洲成?人片| 亚洲国产另类久久久精品| 亚洲成A∨人片在线观看无码| 一本色道久久88亚洲精品综合 | 亚洲精品国产精品国自产网站| 亚洲国产精品成人午夜在线观看| 国产精品高清免费网站| 免费无码成人AV在线播放不卡| 成年性羞羞视频免费观看无限| 亚洲不卡AV影片在线播放|