日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java RMI(远程方法调用) 实例与分析 (转)

發(fā)布時間:2025/4/5 java 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java RMI(远程方法调用) 实例与分析 (转) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目的:

  通過本文,可以加深對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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。