<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 | 夏登成
    謝謝你,讓我明白了遠程方法調用!  回復  更多評論
      

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


    網站導航:
     
    主站蜘蛛池模板: 久久久久国色av免费看| 极品色天使在线婷婷天堂亚洲 | 美丽姑娘免费观看在线观看中文版 | 欧洲黑大粗无码免费| 亚洲性一级理论片在线观看| 99re在线这里只有精品免费| 亚洲欧洲综合在线| AA免费观看的1000部电影| 亚洲免费在线观看视频| 成人奭片免费观看| 亚洲综合欧美色五月俺也去| 成人免费视频一区二区三区| 亚洲高清一区二区三区电影 | 无码人妻一区二区三区免费| 亚洲一级特黄特黄的大片| 午夜免费福利影院| 免费又黄又爽又猛大片午夜 | 日本免费人成网ww555在线| 亚洲色图视频在线观看| 成人免费一区二区无码视频| 免费国产黄网站在线观看动图| 相泽亚洲一区中文字幕| 99久久人妻精品免费一区| 99热亚洲色精品国产88| 免费一级毛片女人图片| 国产成人无码区免费网站| 亚洲欧洲精品久久| 日本不卡在线观看免费v| 一级做a爱过程免费视| 亚洲av无码一区二区乱子伦as| 精品福利一区二区三区免费视频| 亚洲国产欧美一区二区三区| 亚洲性在线看高清h片| 久久国产高潮流白浆免费观看| 亚洲熟妇AV一区二区三区浪潮 | 亚洲人成网址在线观看 | 一区二区三区四区免费视频| 中国亚洲呦女专区| 亚洲中文字幕无码一区| 亚洲一级毛片免费看| 日韩大片免费观看视频播放|