そのため、提起されたタスクではリモートメソッド呼び出しを使用する必要がありました。 Habréについて調べたところ、この問題については何も見つかりませんでした(ドキュメントを読む前に、最初の知り合いとして何かを読みたかったのです)。 java.sun.comで仕様を検討したので、私はあなたと私の最初の記事を急いで共有します。 :)
「RMIとは」
リモートメソッド呼び出し-リモートオブジェクトのメソッドを呼び出すことができるメカニズム。 彼によると、データを準備および送信するためのすべての操作は、クライアントスタブオブジェクト(スタブ)の呼び出されたメソッドにカプセル化されます。 メソッド呼び出し自体は、いくつかの例外を除き、通常のローカルオブジェクトのメソッド呼び出しと同じです。
すべてのパラメーターは値によって渡されます(つまり、通常発生するオブジェクトへのリンクではなくオブジェクトのコピー) -以下で修正されます おかげでコンスタンチンソロマトフ- ローカルオブジェクトは値(コピー)で渡されます
- リモートオブジェクトを送信するときに、エクスポートされた場合、このオブジェクトのスタブが送信されます
- 送信されるオブジェクトはシリアル化可能でなければなりません
- 他のすべての例外的な状況を除いて、リモートメソッドを呼び出すと、RemoteException例外がスローされる場合があります(マーシャライゼーション/アンマーシャライゼーションエラー、データ転送、およびその他の考えられるプロトコルエラー)
また、メソッドを呼び出すときは、リモートクラスではなくリモートインターフェイスで作業していることに注意してください。
「なぜこれが必要なのですか?」
RMIのタスクは、クライアントとサーバーの相互作用の編成です。 つまり、データ転送や前処理(プロトコルなど)を心配する必要はありません。 便利ですか? はい しかし、すべての場合ではありません。 クライアント/サーバー環境がjavaで書かれたプログラムの作業を暗示している場合、RMIはほとんど役に立ちません(ただし、JNIを使用して「抜け出す」ことができます)。
「何かを書きましょう!」
さあ 分散コンピューティングの例を考えてみましょう。 私たちの仕事はこれです:列挙によって最も簡単な方法で素数を検索します。 分散方式で、2からsqrt(n)の除数を選択して数値を確認します。nは確認する数値です。 (「分散コンピューティング」はそのような例の大きな名前です。しかし、私たちは計算していますか?はい!分散していますか?分散しています!)
この方法で問題を解決します:「登録済み」クライアントに検証用の番号を「フィード」するサーバーがあるため、双方向でやり取りします(クライアント->サーバー-登録、サーバー->クライアント-検証用の番号)、これについて説明します2インターフェース:
public interface ClientRegister extends Remote { public void register (PrimeChecker checker) throws RemoteException; } public interface PrimeChecker extends Remote { public boolean check (BigDecimal number) throws RemoteException; } * This source code was highlighted with Source Code Highlighter .
public interface ClientRegister extends Remote { public void register (PrimeChecker checker) throws RemoteException; } public interface PrimeChecker extends Remote { public boolean check (BigDecimal number) throws RemoteException; } * This source code was highlighted with Source Code Highlighter .
public interface ClientRegister extends Remote { public void register (PrimeChecker checker) throws RemoteException; } public interface PrimeChecker extends Remote { public boolean check (BigDecimal number) throws RemoteException; } * This source code was highlighted with Source Code Highlighter .
public interface ClientRegister extends Remote { public void register (PrimeChecker checker) throws RemoteException; } public interface PrimeChecker extends Remote { public boolean check (BigDecimal number) throws RemoteException; } * This source code was highlighted with Source Code Highlighter .
public interface ClientRegister extends Remote { public void register (PrimeChecker checker) throws RemoteException; } public interface PrimeChecker extends Remote { public boolean check (BigDecimal number) throws RemoteException; } * This source code was highlighted with Source Code Highlighter .
public interface ClientRegister extends Remote { public void register (PrimeChecker checker) throws RemoteException; } public interface PrimeChecker extends Remote { public boolean check (BigDecimal number) throws RemoteException; } * This source code was highlighted with Source Code Highlighter .
public interface ClientRegister extends Remote { public void register (PrimeChecker checker) throws RemoteException; } public interface PrimeChecker extends Remote { public boolean check (BigDecimal number) throws RemoteException; } * This source code was highlighted with Source Code Highlighter .
public interface ClientRegister extends Remote { public void register (PrimeChecker checker) throws RemoteException; } public interface PrimeChecker extends Remote { public boolean check (BigDecimal number) throws RemoteException; } * This source code was highlighted with Source Code Highlighter .
ClientRegisterインターフェースは、クライアントが自身をPrimeChecker`aとしてサーバーに登録するために使用します。 サーバーはPrimeCheckerを使用して、確認のためにクライアントに番号を送信します。
既にお気付きのように、リモートインターフェイスは、リモートインターフェイスを直接または間接的に拡張する必要があります。 他の例外の中でも、RemoteExceptionを定義します(上記で説明しました)。
サーバーの実装を開始しましょう(
完全なコード ):
- パブリック クラス PrimeNumbersSearchServerはClientRegisterを実装します{
- ...
- public static void main( String [] args){
- PrimeNumbersSearchServerサーバー= 新しい PrimeNumbersSearchServer();
- {
- ClientRegisterスタブ=(ClientRegister)UnicastRemoteObject.exportObject(server、0);
- レジストリregistry = LocateRegistry.createRegistry(12345);
- registry.bind( "ClientRegister" 、スタブ);
- server.startSearch();
- } catch (例外e){
- システム out .println( "エラーが発生しました:" + e.getMessage());
- System.exit(1);
- }
- }
- }
*このソースコードは、 ソースコードハイライターで強調表示されました。
初期化を分析しましょう:
- ClientRegisterスタブ=(ClientRegister)UnicastRemoteObject.exportObject(server、0);
*このソースコードは、 ソースコードハイライターで強調表示されました。
リモートオブジェクトをエクスポートし、スタブを取得します。スタブを介して、クライアントはオブジェクトのメソッドを呼び出します。 2番目のパラメーターexportObjectは、リモートオブジェクトへの接続に使用されるポートであり、0は任意の空きポートの選択です。 スタブをクライアントに渡す必要があります。 ここでは、まったく異なるオプションが可能です。 3.5 ''フロッピーディスクでクライアントにスタブを渡すこともできます:) RMIレコーダーを使用します。 vm内で作成するか、rmiregistryユーティリティで表される「外部」を使用できます。 最初のオプションを使用しました:
- レジストリregistry = LocateRegistry.createRegistry(12345);
- registry.bind( "ClientRegister" 、スタブ);
*このソースコードは、 ソースコードハイライターで強調表示されました。
レジストラを作成し、ClientRegisterという名前でスタブをバインドします。 レジストラは、ポート12345での接続を受け入れます。
クライアント(
完全なコード ):
- パブリック クラス PrimeNumbersSearchClientはPrimeCheckerを実装します{
- ...
- public static void main( String [] args){
- PrimeNumbersSearchClient client = new PrimeNumbersSearchClient();
- {
- レジストリregistry = LocateRegistry.getRegistry( null 、12345);
- ClientRegisterサーバー=(ClientRegister)registry.lookup( "ClientRegister" );
- PrimeCheckerスタブ=(PrimeChecker)UnicastRemoteObject.exportObject(client、0);
- server.register(スタブ);
- } catch (例外e){
- システム out .println( "エラーが発生しました:" + e.getMessage());
- System.exit(1);
- }
- }
- }
*このソースコードは、 ソースコードハイライターで強調表示されました。
クライアントは、登録するためにサーバースタブを取得する必要があります。
- レジストリregistry = LocateRegistry.getRegistry( null 、12345);
- ClientRegisterサーバー=(ClientRegister)registry.lookup( "ClientRegister" );
*このソースコードは、 ソースコードハイライターで強調表示されました。
リモートレジストラを見つけて、それに関連付けられた「ClientRegister」という名前のスタブを要求します。 最初のパラメーターはLocateRegistry.getRegistry(null、12345)がホスト(nullはlocalhost)で、2番目はポートです。
次に、クライアントリモートオブジェクトをエクスポートし、それをスタブサーバー(既にクライアント)に渡します-登録します。 サーバーは、利用可能なチェッカーのキューにクライアントを追加し、確認のために彼に番号の送信を開始します。 チェックした後、エラーなしで完了した場合、クライアントは再びキューに入ります。
UPD:Javaに移植