<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 閱讀(1545) 評論(1)  編輯  收藏

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

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


    網站導航:
     
    主站蜘蛛池模板: 久久av免费天堂小草播放| 亚洲精华国产精华精华液| jyzzjyzz国产免费观看| 国产精品免费视频播放器| 亚洲欧美第一成人网站7777| 在线观看免费播放av片| 亚洲综合色成在线播放| 久草免费福利在线| 国产亚洲综合网曝门系列| a级毛片在线免费| 国内精品乱码卡1卡2卡3免费| 亚洲黄色在线网站| 91免费国产在线观看| 亚洲va久久久久| 国产乱人免费视频| 久久精品免费网站网| 久久精品7亚洲午夜a| 天天影视色香欲综合免费| 亚洲首页国产精品丝袜| 国产免费av一区二区三区| 成人嫩草影院免费观看| 日韩亚洲变态另类中文| 香港a毛片免费观看 | 久久久久久久99精品免费| 亚洲卡一卡2卡三卡4麻豆| 日本久久久免费高清| 国产成人无码精品久久久久免费| 亚洲AV永久精品爱情岛论坛 | 成全高清视频免费观看| 国产精品亚洲а∨无码播放不卡| 亚洲精品色婷婷在线影院| 一级成人a毛片免费播放| 亚洲综合av一区二区三区| 亚洲无码日韩精品第一页| 无码精品一区二区三区免费视频| 亚洲一日韩欧美中文字幕在线| 亚洲av无码国产精品色在线看不卡| 免费国产叼嘿视频大全网站| 亚洲日日做天天做日日谢| 色噜噜亚洲精品中文字幕| 日韩不卡免费视频|