Java RMI(远程方法调用) 实例与分析 (转)
目的:
通過本文,可以加深對Java RMI的理解,知道它的工作原理,怎么使用等. 也為了加深我自己的理解,故整理成文.不足之處,還望指出.
概念解釋:
RMI(RemoteMethodInvocation):遠程方法調(diào)用,顧名思義,通過遠程的方式調(diào)用非本地對象的方法并返回結(jié)果。使用遠程調(diào)用通常解決本地計算瓶頸問題,例如分布式記算,最近很火的阿爾法狗人機大戰(zhàn),據(jù)說運算使用上千個CPU。
JRMP(java remote method protocol):java遠程方法協(xié)議,這是完成java到j(luò)ava遠程調(diào)用的協(xié)議,基于TCP協(xié)議。
stub與skeleton:這兩個概念下面會用到,這里解釋下,skeleton是放在服務(wù)端的代理,它知道真正的對象在哪。stub是放在客戶端的代理,它記錄了查找和調(diào)用skeleton信息。理解成遠程對象引用也成.
?
容易混淆的概念:
遠程方法調(diào)用與遠程過程調(diào)用的區(qū)別:遠程方法調(diào)用是java獨有的,基于JRMP對象流協(xié)議實現(xiàn),支持傳輸java序列化對象。遠程過程調(diào)用是基于socket技術(shù)實現(xiàn)的,不能傳輸java對象,socket套接字協(xié)議支持多種語言。它們都是基于TCP協(xié)議傳輸。遠程方法調(diào)用傳輸?shù)氖莏ava序列化對象和基本數(shù)據(jù)類型,而遠程過程調(diào)用不支持傳輸對象。
RMI調(diào)用模型:
從宏觀看,想要遠程調(diào)用需要做兩件事情,1,服務(wù)端向本地對象注冊表中注冊能被調(diào)用的遠程對象. 2,客戶端向遠程對象注冊表請求遠程對象的引用.
Java中RMI實現(xiàn):
先通過一個例子了解Java中RMI是怎么用的,然后再根據(jù)代碼分析源碼是如何實現(xiàn)的.
1,先創(chuàng)建遠程對象接口,繼承自Remote(稍后源碼中有分析為什么要有這個接口)
package remote.test;import java.rmi.Remote; import java.rmi.RemoteException; /*** 遠程接口,實現(xiàn)Remote* @author lxz**/ public interface IRemote extends Remote{public String show()throws RemoteException;//聲明方法 }2,接口實現(xiàn),需要繼承UnicastRemoteObject類,等會分析
package remote.test;import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject;/*** 遠程接口實現(xiàn),繼承UnicastRemoteObject* @author lxz**/ public class RemoteImpl extends UnicastRemoteObject implements IRemote{public RemoteImpl()throws RemoteException{}//構(gòu)造方法public String show()throws RemoteException{//調(diào)用方法實現(xiàn)System.out.println("進入");System.out.println(this.toString());return "遠程調(diào)用成功";} }3,服務(wù)端向本地端口1234對象注冊表注冊對象和它的名字
package remote.test;import java.net.MalformedURLException; import java.rmi.AlreadyBoundException; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry;/*** 服務(wù)端啟動,創(chuàng)建端口上的對象注冊列表,向?qū)ο笞员碇凶赃h程調(diào)用對象* @author lxz**/ public class TestServer {public static void main(String[] args) throws MalformedURLException, RemoteException, AlreadyBoundException, InterruptedException {RemoteImpl r = new RemoteImpl();//創(chuàng)建遠程對象Registry rr = LocateRegistry.createRegistry(1234); //創(chuàng)建1234端口上的對象注冊表,如果已經(jīng)創(chuàng)建了就用getRegistry方法獲取rr.bind("testrmi", r);//向注冊表中注冊對象System.out.println(r.toString());} }4,根據(jù)JDK API,以上遠程服務(wù)就算搭建完畢了,下面通過客戶端調(diào)用測試
package remote.test;import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException;/*** 客戶端啟動,獲得遠程的對象注冊表中的對象引用* @author lxz**/ public class TestClient {public static void main(String[] args) throws MalformedURLException, RemoteException, NotBoundException {IRemote r = (IRemote) Naming.lookup("rmi://localhost:1234/testrmi");//獲取遠程1234端口對象注冊表中testrmi的stubString a = r.show();//調(diào)用引用的方法,實際上調(diào)用的是stub,由stub與服務(wù)端交互并返回結(jié)果System.out.println(a);} }
執(zhí)行結(jié)果如下:
------------------------------------------
服務(wù)端:
RemoteImpl[UnicastServerRef [liveRef: [endpoint:[192.168.1.253:58169](local),objID:[-60651394:1539d5944e6:-7fff, -6910034932968554489]]]]
客戶端:
遠程調(diào)用成功
------------------------------------------
這樣就完成了一個遠程對象注冊與遠程對象方法調(diào)用的完整例子. 現(xiàn)在根據(jù)這個例子來分析它為什么要繼承UnicastRemoteObject,實現(xiàn)Remote,向注冊表注冊等等.
首先遠程對象實現(xiàn)類中需要繼承UnicastRemoteObject類,UnicastRemoteObject具有注冊為遠程對象,生成遠程引用的功能等,所有都已經(jīng)被JDK封裝好了,不需要編寫,其中的實現(xiàn)有些是sun包開頭的,不公開.
UnicastRemoteObject繼承關(guān)系:
?
有了遠程對象實現(xiàn)類,看服務(wù)端的啟動邏輯,其中:
Registry rr = LocateRegistry.createRegistry(1234);LocateRegistry類:用于創(chuàng)建或獲取某端口的對象注冊表
LocateRegistry.createRegistry:這個方法表示獲得遠程對象注冊表引用,返回Registry對象
Registry:真正操作遠程對象注冊表的接口
接著,
rr.bind("testrmi", r);利用Registry的對象,把剛剛創(chuàng)建的遠程對象注冊為名稱testrmi. 這里還有一種寫法,效果是一樣的.
LocateRegistry.createRegistry(1234); //創(chuàng)建,如果已經(jīng)創(chuàng)建了就可省略這一句 Naming.bind("rmi://localhost:1234/testrmi", r);//需要帶上端口Naming:與對象注冊表交互的工具類
上面是服務(wù)端從遠程對象創(chuàng)建到對象注冊的整個邏輯.客戶端調(diào)用的邏輯比較簡單,先通過Naming工具類獲取到遠程對象的引用以后,就可以正常使用了
(IRemote) Naming.lookup("rmi://localhost:1234/testrmi");這里返回的"引用"和通常講的對象引用不同,是遠程對象的引用信息.拿到這個"引用"以后就可以像使用真正的對象一樣調(diào)用其中的方法.
?
結(jié)束.
http://www.cnblogs.com/qinggege/p/5306852.html
?
總結(jié)
以上是生活随笔為你收集整理的Java RMI(远程方法调用) 实例与分析 (转)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: x264代码剖析(十四):核心算法之宏块
- 下一篇: C# asp.net mvc 配置多个r