本文章共分為三部分
- RMI簡介
- RMI原理
- RMI使用
- RMI實戰
下面詳細介紹
一 RMI簡介
遠程方法調用(RMI)顧名思義是一臺機器上的程序調用另一臺機器上的方法,其主要目的就是要使運行在不同的計算機中的對象之間的調用表現得像本地調用一樣。從而可以實現分布式計算。
二 RMI原理
簡單來說,用戶知道工匠的名字,知道工匠的地址,然后用戶通過工匠的地址和名字去找到工匠,讓工匠干活。
RMI 應用程序通常包括兩個獨立的程序:服務器程序和客戶機程序。RMI 需要將行為的定義與行為的實現分別定義, 并允許將行為定義代碼與行為實現代碼存放并運行在不同的 JVM 上。在 RMI 中, 遠程服務的定義是存放在繼承了 Remote 的接口中。遠程服務的實現代碼存放在實現該定義接口的類中。RMI 支持兩個類實現一個相同的遠程服務接口: 一個類實現行為并運行在服務器上, 而另一個類作為一個遠程服務的代理運行在客戶機上。客戶程序發出關于代理對象的調用方法, RMI 將該調用請求發送到遠程 JVM 上, 并且進一步發送到實現的方法中。實現方法將結果發送給代理, 再通過代理將結果返回給調用者。
RMI 構建三個抽象層, 高層覆蓋低層, 分別負責Socket通信, 參數和結果的序列化和反序列化等工作。存根( Stub) 和骨架( Skeleton) 合在一起形成了 RMI 構架協議。下面的引用層被用來尋找各自的通信伙伴, 在這一層還有一個提供名字服務的部分, 稱為注冊表( registry) 。最下一層是傳輸層, 是依賴于 TCP/IP 協議實現客戶機與服務器的互聯。
當客戶端調用遠程對象方法時, 存根負責把要調用的遠程對象方法的方法名及其參數編組打包,并將該包向下經遠程引用層、傳輸層轉發給遠程對象所在的服務器。通過 RMI 系統的 RMI 注冊表實現的簡單服務器名字服務, 可定位遠程對象所在的服務器。該包到達服務器后, 向上經遠程引用層, 被遠程對象的 Skeleton 接收, 此 Skeleton 解析客戶包中的方法名及編組的參數后, 在服務器端執行客戶要調用的遠程對象方法, 然后將該方法的返回值( 或產生的異常) 打包后通過相反路線返回給客戶端, 客戶端的 Stub 將返回結果解析后傳遞給客戶程序。事實上, 不僅客戶端程序可以通過存根調用服務器端的遠程對象的方法, 而服務器端的程序亦可通過由客戶端傳遞的遠程接口回調客戶端的遠程對象方法。在分布式系統中, 所有的計算機可以是服務器, 同時又可以是客戶機。
三 RMI使用
四 RMI實戰
GoldbachDefine
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface GoldbachDefine extends Remote{
public String checkNum(int num) throws RemoteException;
}
GoldbachDefineImp
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class GoldbachDefineImp extends UnicastRemoteObject implements GoldbachDefine {
public GoldbachDefineImp() throws RemoteException {
// TODO Auto-generated constructor stub
super();
}
@Override
public String checkNum(int num) throws RemoteException {
// TODO Auto-generated method stub
for(int i=2;i<(num/2+1);i++){
if(isPrimeNum(i)&&isPrimeNum(num-i)){
return "the two number is "+i+"and "+(num-i);
}
}
return 2333333+"";
}
public Boolean isPrimeNum(int num){
for(int i=2;i<(num/2+1);i++){
if(num%i==0){
return false;
}
}
return true;
}
}
GoldbachServer
import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
public class GoldbachServer {
public static void main(String args[])throws RemoteException,MalformedURLException,AlreadyBoundException{
GoldbachDefine goldbach;
goldbach=new GoldbachDefineImp();
//register object
LocateRegistry.createRegistry(8888);
//bing the object to server
Naming.bind("rmi://localhost:8888/Goldbach", goldbach);
System.out.println("server:begin to listen");
}
}
GoldbachClient
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
public class GoldbachClient {
public static void main(String args[])throws MalformedURLException,RemoteException,NotBoundException{
//find register object
GoldbachDefine goldbach = (GoldbachDefine) Naming.lookup("rmi://localhost:8888/Goldbach");
//output the client result
System.out.println("client:");
System.out.println(goldbach.checkNum(8));
}
}
本文章參考以下文章
維基百科-RMI遠程方法調用
遠程方法調用(RMI)原理與示例
RMI遠程方法調用
以上就是RMI的全部啦。大家加油~