RMI遠程調用時的內外網連接埠映射問題(RMI遠程調用如何穿透防火牆)

來源:互聯網
上載者:User

轉載自:http://www.juuluu.org/html/softDoc/2011/10/19/09/45/wtpnkjxlwt.html

以下是一個RMI項目的實施筆記:

環境:防火牆(XX衛士)   外網IP:x.x.x.135 port:8400/8500   內網IP: x.x.x.90 port:8400/8500

                                  內外網IP及port互相映射. (外網IP是設定的防火牆上的,管理員進行映射配置)

 

1.RMI遠程調用的服務註冊到:內網的8400連接埠上 (不用建立stub/skeleton,不使用預設的1099)

  //LocateRegistry.createRegistry(rmiServerPort); //定義服務註冊與尋找服務連接埠 8400

2.RMI遠程調用的資料通訊連接埠綁定到:內網的8500連接埠上

   // RMISocketFactory.setSocketFactory(new SMRMISocket());  //定義資料轉送連接埠 8500

3.設定訪問外網:x.x.x.135:8400時穿透防火牆訪問內網:x.x.x.90:8400

  //在sun.rmi.server.UnicastRef調用時的服務IP為:x.x.x.135,而不是x.x.x.90(客戶的本地不存在RMI服務嘛)

  //System.setProperty("java.rmi.server.hostname","x.x.x.135"); 

 

4.RMI調用穿透防火牆不是自動的,需要我們手工指定,就如3所指,如果不加設定,在互連網上就不能通過外網IP訪問內網IP上綁定的RMI服務

 

5.通過本項目,明白了RMI可以不用rmic建立stub/skeleton的,也可以不用啟動rmiRegistry而通過程式直接啟動RMI服務,這樣方便了代碼的修改與項目的實施.

 

由於是項目代碼,所以不打包上傳代碼了。簡寫如下:

///////RMI服務端代碼

    String hostIP = InetAddress.getLocalHost().getHostAddress();
      int rmiServerPort = 8400;  //Data Transmission Service為8400
      String bindName = "licenseServer";
       //下面這行代碼不能少,否則當路由器x.x.x.135映射到的內網IP:x.x.x.90時,
       //訪問RMI服務時將導向本地的x.x.x.90,那麼用戶端就是訪問本地x.x.x.90,
       //這絕對錯誤.服務是在公網路由器(含公用IP)的後面,不在客戶的本地
       System.setProperty("java.rmi.server.hostname","x.x.x.135");
      try {
        RMISocketFactory.setSocketFactory(new SMRMISocket());  //定義資料轉送連接埠 8500
        LocateRegistry.createRegistry(rmiServerPort); //定義服務註冊與尋找服務連接埠 8400
      }
      catch (Exception ex) {
        System.out.println("伺服器連接埠綁定時發生錯誤:"+ex.getMessage());
        ex.printStackTrace();
      }
      //建立license產生器的服務物件
      MakeLicense licenseService = new MakeLicenseService();
      //綁定一個服務物件到一個服務連接埠
      //URL format (without the scheme component)
      String bindUrl = "//"+hostIP+":"+ rmiServerPort +"/"+bindName;
      Naming.rebind(bindUrl, licenseService);
      System.out.println(bindUrl+" server is ready.");

 

////SMRMISocket.java

import java.rmi.server.*;
import java.io.*;
import java.net.*;

public class SMRMISocket
    extends RMISocketFactory {

  public Socket createSocket(String host, int port) throws IOException {
    return new Socket(host, port);
  }

  public ServerSocket createServerSocket(int port) throws IOException {
    if (port == 0)
      port = 8500;

    System.out.println("RMI伺服器的註冊與資料轉送連接埠 ="+port);
    return new ServerSocket(port);
  }

}

////用戶端代碼:

private String remoteHost = "x.x.x.135";   //公網IP或區域網路IP
  private int rmiServerPort=8400;  //尋找服務連接埠 8400
  private String bindName = "licenseServer";   //RMI服務名稱
  private int revCount = 0;
  private MakeLicense remoteObject=null;
  public LicenseRequestClient()  {
    try{
//      if(System.getSecurityManager()==null){
//        System.setSecurityManager(new RMISecurityManager());
//      }
      String bindUrl = "//"+remoteHost+":"+ rmiServerPort +"/"+bindName;
      System.out.println("請求的遠程服務URL="+bindUrl);
      MakeLicense remoteObject = (MakeLicense) Naming.lookup(bindUrl);
      this.remoteObject = remoteObject;
//      System.out.print("遠程remoteObject="+remoteObject);
    }
    catch (RemoteException re) {
      System.out.println("RemoteException:" + re);
    }
    catch (NotBoundException nbe) {
      System.out.println("NotBoundException:" + nbe);
    }
    catch (MalformedURLException mfe) {
      System.out.println("MalformedURLException:" + mfe);
    }
  }

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.