プッシュ設定でRMIを使用して簡単なチャットプログラムを作成しようとしています。 プログラムは、内部ネットワーク上で動作しますが、外部ネットワーク上のサーバでプログラムを実行しようとしていたとき、私たちはエラーを取得:外部ネットワーク上のRMI Chatプログラムのプッシュ設定が機能しない
java.rmi.ConnectException: Connection refused to host: 192.168.1.13;
Caused by: java.net.ConnectException: Connection timed out: connect
クライアントがメソッド「放送(文字列を呼び出したときにエラーが発生しましたs) 'を入力します。 このメソッドは、サーバー上にあり、サーバー上のリスナーとして購読している他のクライアントを呼び出します。
クライアントはサーバーに接続できます。レジストリからバインディングを取得し、サーバーからメソッドを呼び出すことができます。
しかし、サーバーがクライアントからメソッドを呼び出そうとすると、このエラーが発生します。
サーバーでは、ポート1099が転送され、ポート1099はファイアウォールで許可されます。
これを可能にする方法はありますか(RMIを使用して)? または、クライアント側のポートを転送する必要がありますか?
サーバー:
try {
String theIp = serverHostExternalIp;
System.setProperty("java.rmi.server.hostname", theIp);
//Implemented this so no random ports will be used
RMISocketFactory.setSocketFactory(new FixedPortRMISocketFactory());
registry = LocateRegistry.createRegistry(PORT_NUMBER);
publisher = new RemotePublisher();
publisher.registerProperty(BINDING_NAME);
UnicastRemoteObject.unexportObject(server, true);
UnicastRemoteObject.exportObject(server, PORT_NUMBER);
UnicastRemoteObject.unexportObject(publisher, true);
UnicastRemoteObject.exportObject(publisher, PORT_NUMBER);
registry.rebind(BINDING_NAME, server);
registry.rebind(PUBLISH_NAME, publisher);
} catch (RemoteException ex) {
System.err.println("[Server] Cannot bind student administration");
System.err.println("[Server] RemoteException: " + ex.getMessage());
}
IChatServer:
public synchronized void tryConnect(String s, IChatClient client) throws RemoteException {
System.out.println("[Server] User connected: " + s);
}
public synchronized void broadcast(String s) throws RemoteException {
// When this line is called, no errors occur, and the string is printed correctly.
System.out.println("[Message] " + s);
//on this line, the server tries to reach to all the clients (all listeners)
//This line of code will generate an error.
publisher.inform(BINDING_NAME, null, s);
}
クライアント:
try {
registry = LocateRegistry.getRegistry(ipAddress, PORT_NUMBER);
mycs = (IChatServer) registry.lookup(BINDING_NAME);
//This method is located on the server and is called without errors.
mycs.tryConnect(userid, this);
publisher = (IRemotePublisherForListener) registry.lookup(PUBLISH_NAME);
publisher.subscribeRemoteListener(this, BINDING_NAME);
} catch (RemoteException ex) {
System.err.println("[Client] Cannot lookup or subscribe publisher");
System.err.println("[Client] RemoteException: " + ex.getMessage());
registry = null;
} catch (NotBoundException e) {
System.err.println("[Client] Cannot lookup or subscribe publisher");
System.err.println("[Client] NotBoundException: " + e.getMessage());
registry = null;
}
2ウェイ接続がありますか?クライアントはサーバ上のメソッドを呼び出すことができますか? – Antoniossss
@Antoniossssはい、チャットプログラムを作成する最良の方法ではないかもしれません。私は、クライアントがメッセージを送信するサーバーに、そしてサーバーがそのメッセージを他のすべてのクライアントにブロードキャストするようにクライアントに指示する必要があります。少なくとも、それは私がそれを理解しているものです。 – Wilmz
一般にPUSHアーキテクチャが必要ですが、RMIは一般的なPULLです。あなたがXMPPのようなチャットのようなコミュニケーション(そしてもっと!)のために既存のテクノロジーを自由に使うのはなぜですか?過去に私はXMPPに基づいてチャットアプリケーションを作成し、メッセージブローカーとしてOpenFireサーバーを使用しました。 メッセージキューを使用して、チャットアプリケーションの目的でPUSHアーキテクチャを実現することもできます。 – Antoniossss