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

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

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

    隨筆-11  評論-10  文章-8  trackbacks-0
    rmi有兩個主要問題:
    1. 調用如何從客戶端傳輸到服務器端
       這個問題的是通過stub來解決的,stub負責和服務器通信,將調用傳輸到服務器并接收
       返回值
    2. 由于stub類可以通過工具生成,但初始化必須在服務器端完成,所有如何將一個可用的
       stub傳輸到客戶端就是我們最關心的問題

    注:在1.4中stub類是必須的,在5.0中使用UnicastRemoteObject類可以不需要stub類
    而由動態生成的Proxy類(實現遠程接口,InvocationHandler是
    RemoteObjectInvocationHandler)代替,具體見5.0的文檔。如果不使用
    UnicastRemoteObject類,則stub類在服務器端是必須的

    rmi的核心問題是如何將一個可用的stub傳輸到客戶端,大致有兩種方法:
    1. 最直觀的方法,服務器和客戶端直接建立連接,用任何可用的協議傳輸stub,缺點顯而
       易見,客戶端必須明確的知道服務器的地址及相關信息
    2. 使用注冊中心,如:rmiregistry和JNDI。這里主要討論使用rmiregistry的情況

    有一點需要注意,這里傳輸的只是stub的實例,而不是stub類的定義。所有stub類文件必須
    在客戶端和服務器端的classpath中,否則會拋出ClassNotFoundException。這樣要求客戶
    端確實有些過分,我們希望客戶端只要遠程接口的定義就夠了,這實際上很容易辦到,下面
    我們就來討論這個問題

    Dynamic code downloading using RMI
    (http://java.sun.com/j2se/1.4.2/docs/guide/rmi/codebase.html)

    要下載類必須設置RMISecurityManager,默認是禁止下載的

    客戶端可以通過網絡自動下載stub,此時stub不需要在客戶端的classpath中,只需要遠程
    接口即可。

    由rmiregistry作為注冊中心的遠程調用

    在服務器綁定遠程對象到rmiregistry時,rmiregistry必須能夠找到該對象的stub,它在三
    個地方尋找:
    1. 啟動它時的CLASSPATH環境變量

    2. 啟動它時所在的文件夾作為classpath尋找

    3. 該stub中的codebase,這個值由服務器通過系統屬性 java.rmi.server.codebase 設置

    若找不到則無法綁定

    客戶端通過rmiregistry lookup到stub對象,虛擬機從兩個位置尋找stub類的定義:
    1. classpath中尋找

    2. stub中的codebase,這個值由rmi服務器通過系統屬性 java.rmi.server.codebase 設置

    由以上分析可見,服務器端只要正確設置了codebase,無論何種情況,遠程調用都能順利完成

    不僅客戶端可以從服務器下載類,服務器也可以從客戶端下載類,只需要在客戶端設置
    codebase,安裝RMISecurityManager即可

    若服務器允許下載類,則客戶端有可能在服務器上運行任何他希望的代碼,如以下代碼:
    // 遠程接口定義
    package
    rmi.server;

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

    public interface Service extends Remote {
    public void hello() throws RemoteException;

    public void runThread(Runnable thread) throws RemoteException;
    }

    // 遠程接口實現,main方法作為服務器
    package
    rmi.server;

    import java.rmi.Naming;
    import java.rmi.RMISecurityManager;
    import java.rmi.RemoteException;
    import java.rmi.server.RemoteStub;
    import java.rmi.server.UnicastRemoteObject;
    import java.security.Permission;

    public class ServiceImpl implements Service {

    private RemoteStub stub;

    private int count;

    public ServiceImpl() throws RemoteException {
    stub
    = UnicastRemoteObject.exportObject(this);
    count
    = 0;
    }

    public void hello() throws RemoteException {
    System.out.println(
    "Hello World: count = " + (++count));
    }

    public void runThread(Runnable thread) throws RemoteException {
    Thread t
    = new Thread(thread);
    t.start();
    }

    public RemoteStub getStub() {
    return stub;
    }

    public static void main(String[] args) {
    System.setProperty(
    "java.rmi.server.ignoreStubClasses", "true");
    System.setProperty(
    "java.rmi.server.codebase",
    "file:///E:\\\\bahamut\\\\JavaWorkspace\\\\rmiserver\\\\classes\\\\");
    if (System.getSecurityManager() == null) {
    System.setSecurityManager(
    new RMISecurityManager() {
    public void checkPermission(Permission p) {
    }
    });
    }
    try {
    ServiceImpl service
    = new ServiceImpl();
    Naming.rebind(
    "service", service);
    System.out.println(
    "Server ready");
    }
    catch (Exception e) {
    e.printStackTrace();
    }
    }

    }

    // 客戶端
    package
    rmi.client;

    import java.rmi.Naming;
    import java.rmi.RMISecurityManager;
    import java.security.Permission;

    import rmi.server.Service;

    public class ServiceClient {

    /**
    *
    @param args
    */
    public static void main(String[] args) {
    System.setProperty(
    "java.rmi.server.codebase",
    "file:///E:\\\\bahamut\\\\JavaWorkspace\\\\rmiclient\\\\classes\\\\");
    if (System.getSecurityManager() == null) {
    System.setSecurityManager(
    new RMISecurityManager() {
    public void checkPermission(Permission p) {
    }
    });
    }
    try {
    Service service
    = (Service) Naming.lookup("service");
    service.hello();
    Runnable runner
    = new Runner();
    service.runThread(runner);
    }
    catch (Exception e) {
    e.printStackTrace();
    }
    }

    }
    package rmi.client;

    import java.io.Serializable;

    public class Runner implements Runnable, Serializable {

    public void run() {
    System.out.println(
    "i'm runner");
    }

    }

    服務器端生成stub并放在classpath中,codebase設置為能找到stub的路徑,運行rmiregistry,
    運行服務器。

    客戶端只需要Service類在classpath中,設置codebase為能找到Runner的路徑,運行客戶端。
    客戶端會從服務器下載stub,服務器會從客戶端下載Runner。Runner可以執行任何操作甚至破壞
    服務器上的數據。

    多次運行客戶端可以發現count在增長,也就是說對于export出的遠程對象,狀態是始終保存的
    posted on 2005-11-11 19:49 JBahamut 閱讀(1540) 評論(1)  編輯  收藏

    評論:
    # re: 關于rmi的研究 2009-03-31 16:14 | 夏登成
    謝謝你,讓我明白了遠程方法調用!  回復  更多評論
      

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 免费h成人黄漫画嘿咻破解版| 日韩精品成人亚洲专区| 久久久久亚洲av无码尤物| sihu国产精品永久免费| 一本色道久久88亚洲综合 | 四虎国产精品免费久久影院| 亚洲美国产亚洲AV| 国产精品国产免费无码专区不卡 | 亚洲色精品aⅴ一区区三区| 久久久受www免费人成| 亚洲乱码无码永久不卡在线| 麻豆精品不卡国产免费看| 成人网站免费观看| 日韩亚洲产在线观看| 国产成人免费ā片在线观看| 曰韩无码AV片免费播放不卡| 久久亚洲国产成人精品无码区| 最近免费中文字幕中文高清| 亚洲人成影院在线| 在线观看免费人成视频色| 久久精品熟女亚洲av麻豆| 亚洲无线观看国产精品| 久久WWW免费人成一看片| 亚洲精品GV天堂无码男同| 亚洲女人被黑人巨大进入| 最近2019免费中文字幕视频三| 最新亚洲卡一卡二卡三新区| www.亚洲一区| 最好看最新的中文字幕免费| 亚洲AV无码成人精品区日韩 | 2022年亚洲午夜一区二区福利| AV免费网址在线观看| 青青草97国产精品免费观看 | 两个人日本WWW免费版| 亚洲精品福利网站| 国产一区二区三区在线免费| 18禁在线无遮挡免费观看网站| 91丁香亚洲综合社区| 综合亚洲伊人午夜网| 成人黄软件网18免费下载成人黄18免费视频 | 777亚洲精品乱码久久久久久|