0

いくつかの基本的なデザインパターンを再コーディングしようとしています。私が利用できるコードスニペットだけがあり、完全に実行されているコード例はありませんでした。1つはプロキシパターンと呼ばれます。

リモート経由でメソッドを呼び出したいだけです。これは私の単純なコードです:

WebService.java

public class WebService extends UnicastRemoteObject implements IRemote {

    private static final long serialVersionUID = 1L;

    public static void main(String[] args) {

        try {
            IRemote service = new WebService();
            Naming.rebind("RemoteCalculator", service);
        } catch (Exception e) {
            e.printStackTrace();
        }       
    }

    /** No arg default constructor */
    public WebService() throws RemoteException {    }

    /** Methods of remote interface */
    @Override
    public double getRoot(double v) throws RemoteException {        
        return Math.sqrt(v);
    }


}

...ここで、IRemoteは、リモートインターフェイスを拡張し、単一のサンプルメソッド(getRoot(double))のシグネチャを定義する単純なインターフェイスです。

そして今、リモートに接続するクラス:

TestProxy.java

public class TestProxy implements Remote{

    /**
     * @param args
     */
    public static void main(String[] args) {        
        new TestProxy().go(args[0]);
    }

    public TestProxy() {}

    public void go(String ip) {
        try {

            System.out.println("Trying to lookup for service ...");

            IRemote service = (IRemote) Naming.lookup("//" + ip + "/RemoteCalculator");

            System.out.println("done");

            double d = service.getRoot(5.0);

            System.out.println(d);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

いくつかのドキュメントに示されているように、rmiregistry.exeを実行していて、rmic.exeを介してWebService_Stub.classを作成しました。(ip-)引数が正常に機能するため、ローカルは127.0.0.1に接続します。ただし、ポート(1099)が開いていて、telnetで確認されていても、インターネット経由で接続する方法はありません。

コマンドラインから始めるとき:

java net.mypackage.remote.TestProxy 78.2.2.2

それは常に結果を与えます:

サービスを検索しようとしています...完了java.rmi.ConnectException:接続がホストに拒否されました:192.168.1.51; ネストされた例外は次のとおりです。java.net.ConnectException:sun.rmi.transport.tcp.TCPChannel.createConnection(Unknown Source)at sun.rmi.transport.tcp.TCPChannel.createConnection(Unknown Source)at sun.rmi.transport.tcp.TCPEndpoint.newSocket(Unknown Source)atsun.rmiで接続がタイムアウトしました.transport.tcp.TCPChannel.newConnection(Unknown Source)at sun.rmi.server.UnicastRef.invoke(Unknown Source)at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unkn own Source)atjava.rmi.server.RemoteObjectInvocationHandler。 $ Proxy1.getRoot(Unknown Source)at net.gerdsmeier.remote.TestProxy.go(TestProxy.java:39)at net.gerdsmeier.remote.TestProxy.main(TestProxy.java:22)のinvoke(Unknown Source)原因:java.net。

ここで、192.168.1.51は私のローカルIPアドレスです(つまり、ポート転送は正常に機能します)。

4

2 に答える 2

0

わかりました。WebサービスがNATの背後にあり、RMIレジストリに到達するために1099にポート転送を設定していると思います。これはたりない。リモートオブジェクトは、1099とは異なるポートでリッスンします。このポートへのポートフォワーディングを設定しないと、接続できなくなるため、double d = service.getRoot(5.0)回線で例外が発生します。

問題は、どのポートを転送するかです。ポートを指定しない場合、RMIはランダムに1つの上位ポートを選択します。ただし、 UnicastRemoteObjectコンストラクターのバージョンを使用してポートを指定できます。したがって、ポート番号を選択し、IRemote service = new WebService([portnumber]);そのポートでポート転送を実行および設定することもできます。

それがそれを切るかどうか見てください!

于 2012-09-26T16:07:48.407 に答える
-1

さて、私は問題の一部を解決しました。サーバースタブのロジックの背後にあります。

サーバー側では、行を追加してグローバルホスト名に関する情報を追加する必要があります

System.setProperty("java.rmi.server.hostname",Util.getGlobalAddress().getHostAddress());

... Util クラスは次のようになります。

public class Util{

  /**
   * Finds this computer's global IP address
   * 
   * @return The global IP address, or null if a problem occurred
   */
  public static Inet4Address getGlobalAddress()
  {
    try
    {
      URLConnection uc = new URL( "http://vallentinsource.com/globalip.php" ).openConnection();
      BufferedReader br = new BufferedReader( new InputStreamReader( uc.getInputStream() ) );
      return ( Inet4Address ) InetAddress.getByName( br.readLine() );
    }
    catch( MalformedURLException e )
    {
      e.printStackTrace();
    }
    catch( IOException e )
    {
      e.printStackTrace();
    }

    return null;

  }
}

これは一方向で動作します。つまり、次のようなクライアント側の呼び出しです。

service.printName("Pete");

サーバー側で正常に動作します。一方で ...

d = service.getRoot(5.0);
System.out.println(d);

... クライアントではまだ動作しません。エラーは発生しませんが、結果は得られません。でも。クライアントのIPアドレス/ホスト名も追加することで修正できます。

System.setProperty("java.rmi.client.hostname", "ip.of.client.pc");

しかし、サーバーは事前にすべてのクライアント アドレスを知ることはできません。とにかく:これは回避策であり、場合によっては役立つかもしれません。

于 2012-09-26T19:24:54.783 に答える