以下の長い答えの要約:私が抱えていた問題(RMI接続の両端でサーバーとコールバックポートを制限する)を解決するには、クライアントとサーバーのソケットファクトリの2つのペアを作成する必要がありました。
より長い答えが続きます:
コールバックの問題に対する私たちの解決策は、基本的に3つの部分で構成されていました。1つ目は、オブジェクトのラッピングであり、クライアントからサーバーへの接続に使用されているのか、サーバーからクライアントへのコールバックに使用されているのかを指定する機能が必要でした。の拡張機能を使用すると、使用するUnicastRemoteObject
クライアントおよびサーバーソケットファクトリを指定できるようになりました。ただし、ソケットファクトリをロックダウンするのに最適な場所は、リモートオブジェクトのコンストラクタです。
public class RemoteObjectWrapped extends UnicastRemoteObject {
// ....
private RemoteObjectWrapped(final boolean callback) throws RemoteException {
super((callback ? RemoteConnectionParameters.getCallbackPort() : RemoteConnectionParameters.getServerSidePort()),
(callback ? CALLBACK_CLIENT_SOCKET_FACTORY : CLIENT_SOCKET_FACTORY),
(callback ? CALLBACK_SERVER_SOCKET_FACTORY : SERVER_SOCKET_FACTORY));
}
// ....
}
したがって、最初の引数はオブジェクトが要求を予期している部分を指定し、2番目と3番目はこのリモートオブジェクトを駆動する接続の両端で使用されるソケットファクトリを指定します。
接続で使用されるポートを制限したかったので、RMIソケットファクトリを拡張してポートをロックダウンする必要がありました。これが私たちのサーバーとクライアントの工場のスケッチです:
public class SpecifiedServerSocketFactory implements RMIServerSocketFactory {
/** Always use this port when specified. */
private int serverPort;
/**
* @param ignoredPort This port is ignored.
* @return a {@link ServerSocket} if we managed to create one on the correct port.
* @throws java.io.IOException
*/
@Override
public ServerSocket createServerSocket(final int ignoredPort) throws IOException {
try {
final ServerSocket serverSocket = new ServerSocket(this.serverPort);
return serverSocket;
} catch (IOException ioe) {
throw new IOException("Failed to open server socket on port " + serverPort, ioe);
}
}
// ....
}
上記のサーバーソケットファクトリは、以前に指定したポートのみがこのファクトリによって使用されることを保証することに注意してください。クライアントソケットファクトリは、適切なソケットファクトリとペアにする必要があります(そうしないと、接続できなくなります)。
public class SpecifiedClientSocketFactory implements RMIClientSocketFactory, Serializable {
/** Serialization hint */
public static final long serialVersionUID = 1L;
/** This is the remote port to which we will always connect. */
private int remotePort;
/** Storing the host just for reference. */
private String remoteHost = "HOST NOT YET SET";
// ....
/**
* @param host The host to which we are trying to connect
* @param ignoredPort This port is ignored.
* @return A new Socket if we managed to create one to the host.
* @throws java.io.IOException
*/
@Override
public Socket createSocket(final String host, final int ignoredPort) throws IOException {
try {
final Socket socket = new Socket(host, remotePort);
this.remoteHost = host;
return socket;
} catch (IOException ioe) {
throw new IOException("Failed to open a socket back to host " + host + " on port " + remotePort, ioe);
}
}
// ....
}
したがって、双方向接続を同じポートセットに維持するために残っているのは、クライアント側にコールバックしていることを認識するロジックだけです。そのような状況では、リモートオブジェクトのファクトリメソッドが、コールバックパラメーターをtrueに設定してRemoteObjectWrapperコンストラクターを一番上に呼び出すことを確認してください。