轉載過來的java_rmi

chyx413332087 13年前發布 | 1K 次閱讀

RMI和corba是兩種最重要和使用最廣泛的分布式對象系統。 每種都有它的長處和短處。這兩種系統都在從電子商務到衛生保健等不同的行業成功的使用。在項目中使用這兩種分布機制中的任何一種都是一項很困難的任務。本文介紹了RMI和corba的機理和最主要的是顯示了如何開發一個有用的程序(一個從遠程站點下載文件的程序)。于是有以下內容:

  • 一個分布式系統的簡介

  • 一個RMI和corba的簡介

  • 讓你體驗開發一個RMI和corba程序的滋味。

  • 說明如何使用RMI和corba從遠程機器交換文件

  • 提供一個RMI和Corba的比較。
  • </UL>

    客戶/服務端模式

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

    分布式對象模式

    分布式對象系統是一個對象集合,通過定義很完善的統一的接口來分隔開的要求服務(客戶端)和功能服務(服務端)。換句話說客戶端和公共服務的提供分隔開,這些服務包括數據表現和執行的代碼。這是一個分辨分布式對象模式和客戶/服務模式的主要不同。

    在分布式對象模式里,客戶端發送一個消息到一個對象,由這個對象解釋這個消息然后決定應該由什么服務來完成。這個服務,方法或選擇的完成可能是被一個對象或是被一個broker。RMI和corba就是這種模式的例子。

    RMI

    RMI是一個分布式對象模式。它使得使用java開發分布式程序更加容易。由于不需要設計協議(這基本是一個錯誤的任務) 使得使用RMI開發分布式程序比使用socket更加容易。在RMI里面設計者就象在調用一個本地的類的方法一樣,而實際上是在調用的時候相應的參數被發送到遠端的對象和然后被解釋。最后結果返回給調用者。

    一個 RMI應用的流程

    使用 RMI開發一個分布式應用包括如下幾個步驟
    1)定義一個遠端的接口
    2)實現這個遠端的接口
    3)開發一個服務端
    4)開發一個客戶端
    5)生成Stubs 和Skeletons,運行RMI注冊器,服務端 和客戶端
    我們現在通過開發一個文件交換程序來解釋這些步驟

    例子:文件交換程序

    這個應用允許客戶端從服務端交換(或下載)所有類型的文件。第一步是定義一個遠程的接口,這個接口指定了的簽名方法將被服務端提供和被客戶端調用。

    定義一個遠程接口

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

    代碼例子1: FileInterface.java

    import java.rmi.Remote;
    import java.rmi.RemoteException;

    public interface FileInterface extends Remote { public byte[] downloadFile(String fileName) throws RemoteException; } </PRE>

    注意接口FileInterface的如下特征:

    • 它必須定義成public,這是為了讓客戶端能夠通過調用遠程接口來間接調用遠程的對象。

    • 必須使用從Remote接口擴展過來,這是創建一個遠程的對象的需要。

    • 每個接口方法中必須拋出java.rmi.RemoteException錯誤。
    • </UL>

      實現遠程的接口

      下一步是實現遠程的接口FileInterface。實現的例子在代碼例子 2中列出。類FileImpl從UnicastRemoteObject擴展來。這顯示出FileImpl類是用來創建一個單獨的,不能復制的,遠程的對象,
      這個對象使用RMI 的默認的基于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); } } } </PRE>

      編寫服務端
      第3步是實現一個服務端。有3件事服務端需要去做:
      1)創建一個RMISecurityManager實例,然后安裝它。
      2)創建一個遠程對象的實例(這個例子中是FileImpl )
      3)使用RMI注冊工具來注冊這個對象。
      代碼例子 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(); } } } </PRE>

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

      編寫客戶端 下一步是編寫一個客戶端,客戶端可以遠程調用遠程接口(FileInterface)中說明的任何一個方法。無論如何實現,客戶端必須先從RMI注冊工具獲得一個遠程對象的引用。當引用獲得后方法downloadFile 被調用。客戶端的例子在代碼例子4中,執行過程中客戶端從命令行中獲得兩個參數,第一個是要下載的文件名,第二個是要下載的機器的地址。對應地址的機器上運行服務端。

      代碼例子 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(); } } } </PRE>

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


 本文由用戶 chyx413332087 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!