JavaRush /Java Blog /Random-JA /RMI: 使用方法

RMI: 使用方法

Random-JA グループに公開済み
こんにちは!今日は、かなり興味深いトピックであるRMIについて見ていきます。これはRemote Method Invocationの略です。 RMI: 使用方法 - 1RMI を使用すると、2 つのプログラムが異なるコンピューター上にある場合でも、相互に通信するように教えることができます。かっこいいね?:) でも、それはそれほど難しいことではありません。今日の講義では、RMI インタラクションがどのような部分で構成され、どのように設定するかを理解します。最初に必要なのはクライアントサーバーです。コンピューター用語を深く掘り下げる必要はありません。RMI の場合、これらは単に 2 つのプログラムです。それらの 1 つは何らかのオブジェクトを含み、2 番目はこのオブジェクトのメソッドを呼び出します。あるプログラム内で別のプログラム内にあるオブジェクトのメソッドを呼び出す - これはこれまで一度も行ったことがないものです。試してみる時が来ました!:) 荒野で溺れないように、プログラムをシンプルにしてください。一般に、サーバーはクライアントが要求する何らかの計算を実行します。それは私たちにとっても同じでしょう。サーバーとして単純な計算プログラムを用意します。彼女に残された方法はただ一つ―― multiply()。クライアント プログラムから送信された 2 つの数値を乗算し、結果を返します。まず第一に、インターフェースが必要です。
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Calculator extends Remote {

   int multiply(int x, int y) throws RemoteException;
}
なぜインターフェースが必要なのでしょうか? 実際、RMI の作業は、前の講義で学習したプロキシの作成に基づいています。そして、プロキシの操作は、おそらく覚えているとおり、クラスではなくインターフェイスのレベルで正確に実行されます。私たちのインターフェースには 2 つの重要な要件があります。
  1. リモート トークン インターフェイスを継承する必要があります。
  2. そのすべてのメソッドは RemoteException をスローする必要があります (これは IDE では自動的に行われないため、手動で記述する必要があります)。
次に、インターフェイスを実装するサーバー クラスを作成する必要がありますCalculatorRMI: 使用方法 - 2ここでもすべて非常に単純です。
import java.rmi.RemoteException;

public class RemoteCalculationServer implements Calculator {

   @Override
   public int multiply(int x, int y) throws RemoteException {
       return x*y;
   }

}
ここでコメントすることはあまりありません :) 次に、サーバー計算クラスを構成して起動するサーバー プログラムを作成する必要があります。次のようになります。
import java.rmi.AlreadyBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

public class ServerMain {

   public static final String UNIQUE_BINDING_NAME = "server.calculator";

   public static void main(String[] args) throws RemoteException, AlreadyBoundException, InterruptedException {

       final RemoteCalculationServer server = new RemoteCalculationServer();

       final Registry registry = LocateRegistry.createRegistry(2732);

       Remote stub = UnicastRemoteObject.exportObject(server, 0);
       registry.bind(UNIQUE_BINDING_NAME, stub);

       Thread.sleep(Integer.MAX_VALUE);

   }
}
それを理解してみましょう :) 最初の行では、ある種の文字列変数を作成します。
public static final String UNIQUE_BINDING_NAME = "server.calculator";
この文字列は、リモート オブジェクトの一意の名前です。この名前によって、クライアント プログラムはサーバーを見つけることができます。これについては後で説明します。次に、計算機オブジェクトを作成します。
final RemoteCalculationServer server = new RemoteCalculationServer();
ここではすべてが明らかです。以下はさらに興味深いものです。
final Registry registry = LocateRegistry.createRegistry(2732);
レジストリと呼ばれるこのものは、削除されたオブジェクトのレジストリです。「削除」とは、コンピュータからオブジェクトを削除したという意味ではなく、このレジスタのオブジェクトが他のプログラムからリモートでアクセスできるという事実です :)LocateRegistry.createRegistry()メソッドに番号 2732 を渡しました。これはポート番号です。ポートが何なのかわからない場合は、ここで読むことができますが、今のところ、これは他のプログラムがオブジェクト レジストリを見つけるための固有の番号であることを覚えておく必要があります (これは以下にも表示されます)。次へ移りましょう。次の行で何が起こるかを見てみましょう。
Remote stub = UnicastRemoteObject.exportObject(server, 0);
この行でスタブを作成します。 スタブは、リモート呼び出しプロセス全体をその内部にカプセル化します。これがRMIの最も重要な要素であると言えます。彼女は何をやっている?
  1. メソッドのリモート呼び出しに関するすべての情報を受け取ります。
  2. メソッドにパラメーターがある場合、スタブはそれらを逆シリアル化します。この点に注目してください!リモート呼び出しのメソッドに渡すパラメータはシリアル化可能である必要があります (結局のところ、パラメータはネットワーク経由で送信されます)。私たちにはそのような問題はありません。単に数字を送信するだけです。ただし、オブジェクトを転送する場合は、それを忘れないでください。
  3. その後、目的のメソッドを呼び出します。
UnicastRemoteObject.exportObject()サーバー計算機オブジェクトをメソッドに渡します。このようにして、そのメソッドをリモートから呼び出すことが可能になります。やるべきことは 1 つだけ残っています。
registry.bind(UNIQUE_BINDING_NAME, stub);
最初に思いついた名前でリモート オブジェクト レジストリにスタブを「登録」します。これでクライアントはそれを見つけることができます。最後にプログラムのメインスレッドをスリープ状態にしていることに気づいたかもしれません。
Thread.sleep(Integer.MAX_VALUE);
サーバーを長期間稼働し続ける必要があるだけです。IDEa で 2 つのメソッドを一度に実行します。最初にサーバー メソッド (既に作成したmain()クラス内)、次にクライアント メソッド (以下に記述するクラス内) を実行します。クライアントの起動中にサーバー プログラムがダウンしないことが重要なので、単に長時間スリープ状態にします。まだ動作します:) これで、サーバーメソッドを実行できるようになりました。実行して、クライアント プログラムが何らかのメソッドを呼び出すまで待ち​​ます :) 次に、クライアント プログラムを作成しましょう。数値をサーバーに送信して乗算します。 ServerMainClientMainmain()
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class ClientMain {

   public static final String UNIQUE_BINDING_NAME = "server.calculator";

   public static void main(String[] args) throws RemoteException, NotBoundException {

       final Registry registry = LocateRegistry.getRegistry(2732);

       Calculator calculator = (Calculator) registry.lookup(UNIQUE_BINDING_NAME);

       int multiplyResult = calculator.multiply(20, 30);

       System.out.println(multiplyResult);
   }
}
彼女は単純そうに見えます。何が起きてる?まず、クライアントは、リモートで呼び出すメソッドのオブジェクトの一意の名前を認識している必要があります。したがって、クライアント プログラムでも変数を作成しpublic static final String UNIQUE_BINDING_NAME = "server.calculator"; 、メソッド内でmain()リモート オブジェクトのレジスタにアクセスします。これを行うには、メソッドを呼び出してLocateRegistry.getRegistry()、ServerMain プログラムでレジスタが作成されたポート番号 (ポート 2732) を渡す必要があります (この番号は例のために選択されています。別の番号を使用してみても構いません)。
final Registry registry = LocateRegistry.getRegistry(2732);
あとは、レジスタから目的のオブジェクトを取得するだけです。彼のユニークな名前を知っているので簡単です!
Calculator calculator = (Calculator) registry.lookup(UNIQUE_BINDING_NAME);
型キャストに注意してください。結果のオブジェクトを具体的なクラスではなくインターフェイスCalculator RemoteCalculationServerにキャストします。講義の冒頭で述べたように、RMI はプロキシの使用に基づいているため、リモート呼び出しはクラスではなくインターフェイスのメソッドに対してのみ使用できます。最後に、multiply()オブジェクトのメソッドをリモートで呼び出し、結果をコンソールに出力します。
int multiplyResult = calculator.multiply(20, 30);
System.out.println(multiplyResult);
ずっと前にmain()クラスで メソッドを起動しましたが、今度はクライアント プログラムでメソッドを起動します。 コンソール出力: 600 以上です。私たちのプログラム(2つでも!)はその機能を正常に果たしました:) 時間と希望があれば、少し多様化することができます。たとえば、電卓が 4 つの標準演算をすべてサポートし、数値ではなくオブジェクトがパラメータとして渡されることを確認してください。追加資料として、ここで記事と例をご覧ください。 ServerMainmain()ClientMainCalculationInstance(int x, int y) 次のクラスでお会いしましょう!:)
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION