ホームページ  >  記事  >  Java  >  Java RMI リモート呼び出し手順の分析

Java RMI リモート呼び出し手順の分析

王林
王林転載
2021-02-19 09:50:222057ブラウズ

Java RMI リモート呼び出し手順の分析

まず Java RMI の定義を見てみましょう:

RMI (Remote Method Invocation、リモート メソッド呼び出し) は、Java を使用して JDK1.2 に実装されています。分散アプリケーションを開発する Java の機能が大幅に強化されます。人気のあるネットワーク開発言語としての Java の大きな力は、分散ネットワーク アプリケーションを開発する強力な機能に反映されており、RMI は 100% 純粋な Java ネットワーク分散アプリケーション システムを開発するためのコア ソリューションの 1 つです。実際、これは RPC の Java バージョンと考えることができます。しかし、従来の RPC は分散オブジェクト システムにはうまく適用できません。 Java RMI は、異なるアドレス空間に格納されたプログラム レベルのオブジェクト間の通信をサポートし、リモート オブジェクト間のシームレスなリモート呼び出しを実現します。

RMI リモート呼び出し手順

RMI の相互作用図:

Java RMI リモート呼び出し手順の分析

RMI は 3 つの部分で構成され、最初の部分は rmiregistry (JDK が提供する) です。 1 つは独立して実行できるプログラム (bin ディレクトリ内)、2 つ目はリモート オブジェクトを外部に提供するサーバー側プログラム、3 つ目はリモート オブジェクトのメソッドを呼び出すクライアント側プログラムです。
まず、rmiregistry サービスを開始します。開始時に、サービスがリッスンするポートを指定することも、デフォルトのポート (1099) を使用することもできます。
2 番目に、サーバーはまずローカルでサービスを提供する実装クラスをインスタンス化し、次に Naming/Context/Registry (以下の例で使用されているレジストリ) のバインドまたは再バインド メソッドと、RMI によって提供される他のクラスを使用して、実装のみをインスタンス化します。これで、クラスは rmiregistry に登録され、名前付きで外部に公開されます。
最後に、クライアントは、ローカル インターフェイスと既知の名前 (rmiregistry によって公開される名前) を介して RMIService から実装クラスを取得し、Naming/Context/Registry および RMI が提供する他のクラスのルックアップ メソッドを使用します。このように、ローカルにはこのクラスの実装クラスはありませんが、すべてのメソッドがインターフェイス内にあり、オブジェクトのメソッドをリモートから呼び出すことができます。

スタブとバックボーン ネットワーク間の具体的な通信プロセス:

Java RMI リモート呼び出し手順の分析

メソッド呼び出しは、クライアント オブジェクトからスタブとリモート経由で行われます。参照層 (リモート参照層) とトランスポート層 (トランスポート層) を下方向に通過し、ホストに渡され、再度トランスポート層を通過し、リモート呼び出し層とバックボーン ネットワーク (スケルトン) を上方向に通過して、サーバー オブジェクトに到達します。
スタブはリモート サーバー オブジェクトのプロキシとして機能し、クライアントがオブジェクトをアクティブ化できるようにします。
リモート参照層はセマンティクスを処理し、単一または複数のオブジェクトの通信を管理し、呼び出しを 1 つのサーバーに送信するか複数のサーバーに送信するかを決定します。
トランスポート層は実際の接続を管理し、メソッド呼び出しを受け入れることができるリモート オブジェクトを追跡します。
バックボーン ネットワークは、サーバー オブジェクトへの実際のメソッド呼び出しを完了し、戻り値を取得します。
戻り値は、リモート参照層とサーバー側のトランスポート層を介してクライアントに戻され、その後、トランスポート層とリモート呼び出し層を介して上向きに返されます。最後に、スタブは戻り値を取得します。

JAVA RMI の簡単な例

この例は、サーバー側のリモート オブジェクトを呼び出すクライアントの加算および減算メソッドです。具体的な手順は次のとおりです:
1. リモート インターフェイスの定義

import java.rmi.Remote;
import java.rmi.RemoteException;

/**
 * 必须继承Remote接口。
 * 所有参数和返回类型必须序列化(因为要网络传输)。
 * 任意远程对象都必须实现此接口。
 * 只有远程接口中指定的方法可以被调用。
 */
public interface IRemoteMath extends Remote {

  	// 所有方法必须抛出RemoteException
	public double add(double a, double b) throws RemoteException;
	public double subtract(double a, double b) throws RemoteException;
	
}

(学習ビデオ共有: java ビデオ チュートリアル)

2. リモート インターフェイス実装クラス

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import remote.IRemoteMath;

/**
 * 服务器端实现远程接口。
 * 必须继承UnicastRemoteObject,以允许JVM创建远程的存根/代理。
 */
public class RemoteMath extends UnicastRemoteObject implements IRemoteMath {

	private int numberOfComputations;
	
	protected RemoteMath() throws RemoteException {
		numberOfComputations = 0;
	}
	
	@Override
	public double add(double a, double b) throws RemoteException {
		numberOfComputations++;
		System.out.println("Number of computations performed so far = " 
				+ numberOfComputations);
		return (a+b);
	}

	@Override
	public double subtract(double a, double b) throws RemoteException {
		numberOfComputations++;
		System.out.println("Number of computations performed so far = " 
				+ numberOfComputations);
		return (a-b);
	}

}

3. サーバー側

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import remote.IRemoteMath;

/**
 * 创建RemoteMath类的实例并在rmiregistry中注册。
 */
public class RMIServer {

	public static void main(String[] args)  {
		
		try {
			// 注册远程对象,向客户端提供远程对象服务。
			// 远程对象是在远程服务上创建的,你无法确切地知道远程服务器上的对象的名称,
			// 但是,将远程对象注册到RMI Registry之后,
			// 客户端就可以通过RMI Registry请求到该远程服务对象的stub,
			// 利用stub代理就可以访问远程服务对象了。
			IRemoteMath remoteMath = new RemoteMath();  
			LocateRegistry.createRegistry(1099);    
			Registry registry = LocateRegistry.getRegistry();
			registry.bind("Compute", remoteMath);
			System.out.println("Math server ready");
			// 如果不想再让该对象被继续调用,使用下面一行
			// UnicastRemoteObject.unexportObject(remoteMath, false);
		} catch (Exception e) {
			e.printStackTrace();
		}		
		
	}
	
}

4. クライアント end

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import remote.IRemoteMath;

public class MathClient {

	public static void main(String[] args) {
		
		try { 
			// 如果RMI Registry就在本地机器上,URL就是:rmi://localhost:1099/hello
			// 否则,URL就是:rmi://RMIService_IP:1099/hello
			Registry registry = LocateRegistry.getRegistry("localhost");        
			// 从Registry中检索远程对象的存根/代理
			IRemoteMath remoteMath = (IRemoteMath)registry.lookup("Compute");
			// 调用远程对象的方法
			double addResult = remoteMath.add(5.0, 3.0);
			System.out.println("5.0 + 3.0 = " + addResult);
			double subResult = remoteMath.subtract(5.0, 3.0);
			System.out.println("5.0 - 3.0 = " + subResult);			
		}catch(Exception e) {
			e.printStackTrace();
		}
				
	}
	
}

の結果は次のとおりです:

server end

Java RMI リモート呼び出し手順の分析

#client end

Java RMI リモート呼び出し手順の分析

参照:

https://blog.csdn.net/xinghun_4/article/details/45787549

関連する推奨事項:

Java 入門チュートリアル

以上がJava RMI リモート呼び出し手順の分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcsdn.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。