Java RMI接続で使用されるポートを知っていますか?
RMI接続を使用してJavaクライアントアプリケーションをJavaサーバーアプリケーションに接続したい場合、クライアントがサーバーマシンで開く必要があるポートアプリケーションはそれに接続できますか?
サーバーマシンにファイアウォールを設定したいのですが、どのポートを開くべきかわかりません。
RMIは予測不可能なポートを使用するため、通常はファイアウォールを越えて機能しません(1099で開始し、その後ランダムポートで実行されます)。
これらの状況では、一般に、HTTPを介したRMIトンネリングに頼る必要があります。これについては、よく説明されています here 。
これまでのすべての答えは間違っています。レジストリは通常ポート1099を使用しますが、変更できます。しかし、それで話は終わりではありません。リモートオブジェクトもポートを使用しますが、必ずしも1099ではありません。
エクスポート時にポートを指定しない場合、RMIはランダムなポートを使用します。したがって、解決策はエクスポート時にポート番号を指定するです。そして、これは、もしあればファイアウォールで開く必要があるポートです。
リモートオブジェクトがUnicastRemoteObject
を拡張する場合、そのコンストラクターにゼロ以外のポート番号でsuper(port)
を呼び出します。
UnicastRemoteObject
を拡張しない場合は、UnicastRemoteObject.exportObject()
にゼロ以外のポート番号を指定します。
これにはいくつかのしわがあります。
ソケットファクトリを使用せず、最初のリモートオブジェクトをエクスポートするときにゼロ以外のポート番号を指定すると、RMIは、ポート番号を指定せずに、またはゼロを指定して、その後エクスポートされるリモートオブジェクトとそのポートを自動的に共有します。最初のリモートオブジェクトには、LocateRegistry.createRegistry().
で作成されたレジストリが含まれます。したがって、ポート1099でRegistry
を作成すると、そのJVMからエクスポートされた他のすべてのオブジェクトはポート1099を共有できます。
areソケットファクトリを使用しており、RMIServerSocketFactory
にequals()
の適切な実装がある場合、上記と同じことが適用されます。
両方の条件下で、すべてのリモートオブジェクトに同じ非ゼロの明示的なポート番号を使用できます。 createRegistry(1099)
の後に任意の数のsuper(1099)
またはexportObject(..., 1099)
呼び出しが続きます。
RMIでは、ポートに関して、2つの異なるメカニズムが関係しています。
1)デフォルトでは、RMIレジストリはポート1099を使用します
2)リモートオブジェクトのエクスポート時に固定ポートが指定されていない限り、クライアントとサーバー(スタブ、リモートオブジェクト)はランダムポートを介して通信します。通信は、開始ポートとして0を使用するソケットファクトリを介して開始されます。これは、0から65535までの「使用可能なポートを使用する」ことを意味します。
通常、rmiregistryコマンドを使用してサーバーでポートを設定します。コマンドラインでポートを設定できます。または、デフォルトで1099になります
クライアントを変更できる場合は、リモート参照を印刷し、使用しているポートを確認します。例えば。
ServerApi server = (ServerApi) registry.lookup(ServerApi.RMI_NAME);
System.out.println("Got server handle " + server);
次のようなものが生成されます。
サーバーハンドルProxy [ServerApi、RemoteObjectInvocationHandler [UnicastRef [liveRef:[endpoint:172.17.3.190:9001、objID:[-7c63fea8:...
ポートが9001であることがわかります。リモートクラスがポートを指定していない場合、リブート後に変更されます。固定ポートを使用する場合は、リモートクラスコンストラクターが次のように動作することを確認する必要があります。
super(rmiPort)
RMIの実装方法に応じて、レジストリポートを設定できます(レジストリは「一意のサービスポイント」です)。明示的なポートを設定しない場合、レジストリはデフォルトでポート1099を想定します。場合によっては、ファイアウォールがあり、ファイアウォールは、rmi-clientがレジストリの背後にあるスタブとオブジェクトを見ることができないようにします。ファイアウォールによってブロックされている-もちろん。 RmiServiceExporter
を使用してRmiServerを構成する場合、メソッドrmiServiceExporter.setServicePort(port)
を使用してrmiポートを修正し、ファイアウォールでこのポートを開くことができます。
編集:私はこの投稿でこの問題を解決します: http://www.mscharhag.com/Java/java-rmi-things-to-remember
上記の他の回答を参照して、ここに私の見解があります-
クライアント側とサーバー側の両方にポートが関係しています。
サーバー/リモート側では、ポートを指定せずにオブジェクトをエクスポートすると、リモートオブジェクトはランダムポートを使用してリッスンします。
クライアントは、リモートオブジェクトを検索するときに、常にその側でランダムポートを使用し、上記のようにリモートオブジェクトポートに接続します。