RMI 说明
見(jiàn):https://baike.baidu.com/item/RMI/1786244?fr=aladdin
RMI遠(yuǎn)程方法調(diào)用
相關(guān)概述
RMI系統(tǒng)運(yùn)行機(jī)理
RMI應(yīng)用程序通常包括兩個(gè)獨(dú)立的程序:服務(wù)器程序和客戶機(jī)程序。典型的服務(wù)器應(yīng)用程序?qū)?chuàng)建多個(gè)遠(yuǎn)程對(duì)象,使這些遠(yuǎn)程對(duì)象能夠被引用,然后等待客戶機(jī)調(diào)用這些遠(yuǎn)程對(duì)象的方法。而典型的客戶機(jī)程序則從服務(wù)器中得到一個(gè)或多個(gè)遠(yuǎn)程對(duì)象的引用,然后調(diào)用遠(yuǎn)程對(duì)象的方法。RMI為服務(wù)器和客戶機(jī)進(jìn)行通信和信息傳遞提供了一種機(jī)制。 在與遠(yuǎn)程對(duì)象的通信過(guò)程中,RMI使用標(biāo)準(zhǔn)機(jī)制:stub和skeleton。遠(yuǎn)程對(duì)象的stub擔(dān)當(dāng)遠(yuǎn)程對(duì)象的客戶本地代表或代理人角色。調(diào)用程序?qū)⒄{(diào)用本地stub的方法,而本地stub將負(fù)責(zé)執(zhí)行對(duì)遠(yuǎn)程對(duì)象的方法調(diào)用。在RMI中,遠(yuǎn)程對(duì)象的stub與該遠(yuǎn)程對(duì)象所實(shí)現(xiàn)的遠(yuǎn)程接口集相同。調(diào)用stub的方法時(shí)將執(zhí)行下列操作: (1) 初始化與包含遠(yuǎn)程對(duì)象的遠(yuǎn)程虛擬機(jī)的連接; (2) 對(duì)遠(yuǎn)程虛擬機(jī)的參數(shù)進(jìn)行編組(寫(xiě)入并傳輸); (3) 等待方法調(diào)用結(jié)果; (4) 解編(讀取)返回值或返回的異常; (5) 將值返回給調(diào)用程序。為了向調(diào)用程序展示比較簡(jiǎn)單的調(diào)用機(jī)制,stub將參數(shù)的序列化和網(wǎng)絡(luò)級(jí)通信等細(xì)節(jié)隱藏了起來(lái)。在遠(yuǎn)程虛擬機(jī)中,每個(gè)遠(yuǎn)程對(duì)象都可以有相應(yīng)的skeleton(在JDK1.2環(huán)境中無(wú)需使用skeleton)。Skeleton負(fù)責(zé)將調(diào)用分配給實(shí)際的遠(yuǎn)程對(duì)象實(shí)現(xiàn)。它在接收方法調(diào)用時(shí)執(zhí)行下列操作:(1) 解編(讀取)遠(yuǎn)程方法的參數(shù);(2) 調(diào)用實(shí)際遠(yuǎn)程對(duì)象實(shí)現(xiàn)上的方法;(3) 將結(jié)果(返回值或異常)編組(寫(xiě)入并傳輸)給調(diào)用程序。stub和skeleton由rmic編譯器生成。 利用RMI編寫(xiě)分布式對(duì)象應(yīng)用程序需要完成以下工作:(1) 定位遠(yuǎn)程對(duì)象。應(yīng)用程序可使用兩種機(jī)制中的一種得到對(duì)遠(yuǎn)程對(duì)象的引用。它既可用RMI的簡(jiǎn)單命名工具rmiregistry來(lái)注冊(cè)它的遠(yuǎn)程對(duì)象,也可以將遠(yuǎn)程對(duì)象引用作為常規(guī)操作的一部分來(lái)進(jìn)行傳遞和返回。(2)與遠(yuǎn)程對(duì)象通信。遠(yuǎn)程對(duì)象間通信的細(xì)節(jié)由RMI處理,對(duì)于程序員來(lái)說(shuō),遠(yuǎn)程通信看起來(lái)就像標(biāo)準(zhǔn)的Java方法調(diào)用。(3)給作為參數(shù)或返回值傳遞的對(duì)象加載類(lèi)字節(jié)碼。因?yàn)镽MI允許調(diào)用程序?qū)⒓僇ava對(duì)象傳給遠(yuǎn)程對(duì)象,所以,RMI將提供必要的機(jī)制,既可以加載對(duì)象的代碼又可以傳輸對(duì)象的數(shù)據(jù)。在RMI分布式應(yīng)用程序運(yùn)行時(shí),服務(wù)器調(diào)用注冊(cè)服務(wù)程序以使名字與遠(yuǎn)程對(duì)象相關(guān)聯(lián)。客戶機(jī)在服務(wù)器上的注冊(cè)服務(wù)程序中用遠(yuǎn)程對(duì)象的名字查找該遠(yuǎn)程對(duì)象,然后調(diào)用它的方法。系統(tǒng)組成
一個(gè)正常工作的RMI系統(tǒng)由下面幾個(gè)部分組成: ·遠(yuǎn)程服務(wù)的接口定義 ·遠(yuǎn)程服務(wù)接口的具體實(shí)現(xiàn) ·樁(Stub)和框架(Skeleton)文件 ·一個(gè)運(yùn)行遠(yuǎn)程服務(wù)的服務(wù)器 ·一個(gè)RMI命名服務(wù),它允許客戶端去發(fā)現(xiàn)這個(gè)遠(yuǎn)程服務(wù) ·類(lèi)文件的提供者(一個(gè)HTTP或者FTP服務(wù)器) ·一個(gè)需要這個(gè)遠(yuǎn)程服務(wù)的客戶端程序技術(shù)原理
RMI系統(tǒng)結(jié)構(gòu),在客戶端和服務(wù)器端都有幾層結(jié)構(gòu)。 --------- ---------- | 客戶 | |服務(wù)器| ---------- ---------- | | ------------- ---------- | 占位程序| |骨干網(wǎng)| -------------- ----------- | | ------------------------------------ | 遠(yuǎn) 程 引 用 層 | ------------------------------------ | | ------------------------------------ | 傳 輸 層 | ------------------------------------ 方法調(diào)用從客戶對(duì)象經(jīng)占位程序(Stub)、遠(yuǎn)程引用層(Remote Reference Layer)和傳輸層(Transport Layer)向下,傳遞給主機(jī),然后再次經(jīng)傳 輸層,向上穿過(guò)遠(yuǎn)程調(diào)用層和骨干網(wǎng)(Skeleton),到達(dá)服務(wù)器對(duì)象。 占位程序扮演著遠(yuǎn)程服務(wù)器對(duì)象的代理的角色,使該對(duì)象可被客戶激活。 遠(yuǎn)程引用層處理語(yǔ)義、管理單一或多重對(duì)象的通信,決定調(diào)用是應(yīng)發(fā)往一個(gè)服務(wù)器還是多個(gè)。傳輸層管理實(shí)際的連接,并且追追蹤可以接受方法調(diào)用的遠(yuǎn)程對(duì)象。服務(wù)器端的骨干網(wǎng)完成對(duì)服務(wù)器對(duì)象實(shí)際的方法調(diào)用,并獲取返回值。返回值向下經(jīng)遠(yuǎn)程引用層、服務(wù)器端的傳輸層傳遞回客戶端,再向上經(jīng)傳輸層和遠(yuǎn)程調(diào)用層返回。最后,占位程序獲得返回值。 要完成以上步驟需要有以下幾個(gè)步驟: 1、生成一個(gè)遠(yuǎn)程接口 2、實(shí)現(xiàn)遠(yuǎn)程對(duì)象(服務(wù)器端程序) 3、生成占位程序和骨干網(wǎng)(服務(wù)器端程序) 4、編寫(xiě)服務(wù)器程序 5、編寫(xiě)客戶程序 6、注冊(cè)遠(yuǎn)程對(duì)象 7、啟動(dòng)遠(yuǎn)程對(duì)象具體實(shí)現(xiàn)如下: 1、生成一個(gè)遠(yuǎn)程接口 package c15.ptime; importjava.rmi.*; public interface PerfectTimeI extends Remote { long getPerfectTime() throws RemoteException; } 2、實(shí)現(xiàn)遠(yuǎn)程對(duì)象(服務(wù)器端程序) package c15.ptime; import java.rmi.*; importjava.rmi.server.*; importjava.rmi.registry.*; import java. net.*; public class PerfectTime extends UnicastRemoteObject implements PerfectTimeI { public long getPerfectTime() throws RemoteException { return System.currentTimeMillis(); } public PerfectTime() throws RemoteException { super(); } public static void main(String[] args) { try { PerfectTime pt = new PerfectTime(); LocateRegistry.createRegistry(2005); Naming.rebind( "//zhouty:2005/PerfectTime" , pt); System.out.println("Ready to do time"); } catch(Exception e) { e.printStackTrace(); } } } 4、編譯遠(yuǎn)程對(duì)象(服務(wù)器端程序) javac -classpath . -d . PerfectTime.java 5、生成根和干(占位程序和骨干程序) rmic -classpath . -d . c15.ptime.PerfectTime 注:jdk1.2以后的都不需要skeleton,所以如果你用的jdk為5.0版本的, 不要奇怪為什么只產(chǎn)生了stub沒(méi)有skeleton。 6、注冊(cè)遠(yuǎn)程對(duì)象 start rmiregistry 2005 注:綁定服務(wù)的默認(rèn)端口為1099,如果使用了這個(gè)端口,則可以直接使用 start rmiregistry而不需要跟端口 如果這種注冊(cè)遠(yuǎn)程對(duì)象的方法不起作用. 還有一種方法就是在綁定服務(wù)之前使用LocateRegistry.createRegistry(1099) 來(lái)注冊(cè)遠(yuǎn)程對(duì)象. 7、啟動(dòng)服務(wù)器端程序 java-Djava.rmi.server.codebase=file:///d:/TestRMI/ c15.ptime.Per fectTime 8、編寫(xiě)客戶端程序 package c15.ptime; import java.rmi.*; importjava.rmi.registry.*; public class DisplayPerfectTime { public static void main(String[] args) { System.setSecurityManager( new RMISecurityManager()); try { PerfectTimeI t = (PerfectTimeI)Naming.lookup( "192.168.0.171:2005/PerfectTime"); for(int i = 0 ; i < 10; i++) System.out.println("Perfect time =" + t.getPerfectTime()); } catch(Exception e) { e.printStackTrace(); } } } 9、編譯客端程序 javac -classpath . -d . DisplayPerfectTime.java 10、修改JVM的配置文件 (客戶機(jī)和服務(wù)器的都需要經(jīng)過(guò)修改) %JRE_HOME%\policytool.exe 11、啟動(dòng)客戶程序 java -classpath . c15.ptime.DisplayPerfectTime 12、返回結(jié)果 Perfect time =967274884390 Perfect time =967274884450 Perfect time =967274884450 Perfect time =967274884450 Perfect time =967274884500 Perfect time =967274884500 Perfect time =967274884560 Perfect time =967274884610 Perfect time =967274884610 Perfect time =967274884610
RMI(遠(yuǎn)程方法調(diào)用)的優(yōu)點(diǎn)
從最基本的角度看,RMI是Java的遠(yuǎn)程過(guò)程調(diào)用(RPC)機(jī)制。與傳統(tǒng)的RPC系統(tǒng)相比,RMI具有若干優(yōu)點(diǎn),因?yàn)樗荍ava面向?qū)ο蠓椒ǖ囊徊糠帧鹘y(tǒng)的RPC系統(tǒng)采用中性語(yǔ)言,所以是最普通的系統(tǒng)--它們不能提供所有可能的目標(biāo)平臺(tái)所具有的功能。 RMI以Java為核心,可與采用本機(jī)方法與現(xiàn)有系統(tǒng)相連接。這就是說(shuō),RMI可采用自然、直接和功能全面的方式為您提供分布式計(jì)算技術(shù),而這種技術(shù)可幫助您以不斷遞增和無(wú)縫的方式為整個(gè)系統(tǒng)添加Java功能。 RMI的主要優(yōu)點(diǎn)如下: 面向?qū)ο?#xff1a;RMI可將完整的對(duì)象作為參數(shù)和返回值進(jìn)行傳遞,而不僅僅是預(yù)定義的數(shù)據(jù)類(lèi)型。也就是說(shuō),您可以將類(lèi)似Java哈希表這樣的復(fù)雜類(lèi)型作為一個(gè)參數(shù)進(jìn)行傳遞。而在目前的RPC系統(tǒng)中,您只能依靠客戶機(jī)將此類(lèi)對(duì)象分解成基本數(shù)據(jù)類(lèi)型,然后傳遞這些數(shù)據(jù)類(lèi)型,最后在服務(wù)器端重新創(chuàng)建哈希表。RMI則不需額外的客戶程序代碼(將對(duì)象分解成基本數(shù)據(jù)類(lèi)型),直接跨網(wǎng)傳遞對(duì)象。 可移動(dòng)屬性:RMI可將屬性(類(lèi)實(shí)現(xiàn)程序)從客戶機(jī)移動(dòng)到服務(wù)器,或者從服務(wù)器移到客戶機(jī)。例如,您可以定義一個(gè)檢查雇員開(kāi)支報(bào)告的接口,以便察看雇員是否遵守了公司目前實(shí)行的政策。在開(kāi)支報(bào)告創(chuàng)建后,客戶機(jī)就會(huì)從服務(wù)器端獲得實(shí)現(xiàn)該接口的對(duì)象。如果政策發(fā)生變化,服務(wù)器端就會(huì)開(kāi)始返回使用了新政策的該接口的另一個(gè)實(shí)現(xiàn)程序。您不必在用戶系統(tǒng)上安裝任何新的軟件就能在客戶端檢查限制條件--從而向用戶提供爍快的反饋,并降低服務(wù)器的工作量。這樣就能具備最大的靈活性,因?yàn)檎吒淖儠r(shí)只需要您編寫(xiě)一個(gè)新的Java類(lèi),并將其在服務(wù)器主機(jī)上安裝一次即可。 設(shè)計(jì)方式:對(duì)象傳遞功能使您可以在分布式計(jì)算中充分利用面向?qū)ο蠹夹g(shù)的強(qiáng)大功能,如二層和三層結(jié)構(gòu)系統(tǒng)。如果您能夠傳遞屬性,那么您就可以在您的解決方案中使用面向?qū)ο蟮脑O(shè)計(jì)方式。所有面向?qū)ο蟮脑O(shè)計(jì)方式無(wú)不依靠不同的屬性來(lái)發(fā)揮功能,如果不能傳遞完整的對(duì)象--包括實(shí)現(xiàn)和類(lèi)型--就會(huì)失去設(shè)計(jì)方式上所提供的優(yōu)點(diǎn)。 安 全:RMI使用Java內(nèi)置的安全機(jī)制保證下載執(zhí)行程序時(shí)用戶系統(tǒng)的安全。RMI使用專(zhuān)門(mén)為保護(hù)系統(tǒng)免遭惡意小應(yīng)用程序侵害而設(shè)計(jì)的安全管理程序,可保護(hù)您的系統(tǒng)和網(wǎng)絡(luò)免遭潛在的惡意下載程序的破壞。在情況嚴(yán)重時(shí),服務(wù)器可拒絕下載任何執(zhí)行程序。 便于編寫(xiě)和使用:RMI使得Java遠(yuǎn)程服務(wù)程序和訪問(wèn)這些服務(wù)程序的Java客戶程序的編寫(xiě)工作變得輕松、簡(jiǎn)單。遠(yuǎn)程接口實(shí)際上就是Java接口。服務(wù)程序大約用三行指令宣布本身是服務(wù)程序,其它方面則與任何其它Java對(duì)象類(lèi)似。這種簡(jiǎn)單方法便于快速編寫(xiě)完整的分布式對(duì)象系統(tǒng)的服務(wù)程序,并快速地制做軟件的原型和早期版本,以便于進(jìn)行測(cè)試和評(píng)估。因?yàn)镽MI程序編寫(xiě)簡(jiǎn)單,所以維護(hù)也簡(jiǎn)單。 可連接現(xiàn)有/原有的系統(tǒng):RMI可通過(guò)Java的本機(jī)方法接口JNI與現(xiàn)有系統(tǒng)進(jìn)行進(jìn)行交互。利用RMI和JNI,您就能用Java語(yǔ)言編寫(xiě)客戶端程序,還能使用現(xiàn)有的服務(wù)器端程序。在使用RMI/JNI與現(xiàn)有服務(wù)器連接時(shí),您可以有選擇地用Java重新編寫(xiě)服務(wù)程序的任何部分,并使新的程序充分發(fā)揮Java的功能。類(lèi)似地,RMI可利用JDBC、在不修改使用數(shù)據(jù)庫(kù)的現(xiàn)有非Java源代碼的前提下與現(xiàn)有關(guān)系數(shù)據(jù)庫(kù)進(jìn)行交互。 編寫(xiě)一次,到處運(yùn)行:RMI是Java“編寫(xiě)一次,到處運(yùn)行 ”方法的一部分。任何基于RMI的系統(tǒng)均可100%地移植到任何Java虛擬機(jī)上,RMI/JDBC系統(tǒng)也不例外。如果使用RMI/JNI與現(xiàn)有系統(tǒng)進(jìn)行交互工作,則采用JNI編寫(xiě)的代碼可與任何Java虛擬機(jī)進(jìn)行編譯、運(yùn)行。 分布式垃圾收集:RMI采用其分布式垃圾收集功能收集不再被網(wǎng)絡(luò)中任何客戶程序所引用的遠(yuǎn)程服務(wù)對(duì)象。與Java虛擬機(jī)內(nèi)部的垃圾收集類(lèi)似,分布式垃圾收集功能允許用戶根據(jù)自己的需要定義服務(wù)器對(duì)象,并且明確這些對(duì)象在不再被客戶機(jī)引用時(shí)會(huì)被刪除。 并行計(jì)算:RMI采用多線程處理方法,可使您的服務(wù)器利用這些Java線程更好地并行處理客戶端的請(qǐng)求。Java分布式計(jì)算解決方案:RMI從JDK 1.1開(kāi)始就是Java平臺(tái)的核心部分,因此,它存在于任何一臺(tái)1.1 Java虛擬機(jī)中。所有RMI系統(tǒng)均采用相同的公開(kāi)協(xié)議,所以,所有Java 系統(tǒng)均可直接相互對(duì)話,而不必事先對(duì)協(xié)議進(jìn)行轉(zhuǎn)換。RMI與CORBA的關(guān)系
RMI 和 CORBA 常被視為相互競(jìng)爭(zhēng)的技術(shù),因?yàn)閮烧叨继峁?duì)遠(yuǎn)程分布式對(duì)象的透明訪問(wèn)。但這兩種技術(shù)實(shí)際上是相互補(bǔ)充的,一者的長(zhǎng)處正好可以彌補(bǔ)另一者的短處。RMI 和 CORBA 的結(jié)合產(chǎn)生了RMI-IIOP,RMI-IIOP 是企業(yè)服務(wù)器端 Java 開(kāi)發(fā)的基礎(chǔ)。 1997 年,IBM 和 Sun Microsystems啟動(dòng)了一項(xiàng)旨在促進(jìn) Java 作為企業(yè)開(kāi)發(fā)技術(shù)的發(fā)展的合作計(jì)劃。兩家公司特別著力于如何將 Java 用作服務(wù)器端語(yǔ)言,生成可以結(jié)合進(jìn)現(xiàn)有體系結(jié)構(gòu)的企業(yè)級(jí)代碼。所需要的就是一種遠(yuǎn)程傳輸技術(shù),它兼有 Java 的 RMI(Remote Method Invocation,遠(yuǎn)程方法調(diào)用)較少的資源占用量和更成熟的 CORBA(Common Object Request Broker Architecture,公共對(duì)象請(qǐng)求代理體系結(jié)構(gòu))技術(shù)的健壯性。出于這一需要,RMI-IIOP問(wèn)世了,它幫助將 Java 語(yǔ)言推向了目前服務(wù)器端企業(yè)開(kāi)發(fā)的主流語(yǔ)言的領(lǐng)先地位。 RMI示例 Java遠(yuǎn)程方法調(diào)用(RMI)提供了Java程序語(yǔ)言的遠(yuǎn)程通訊功能,這種特性使客戶機(jī)上運(yùn)行的程序可以調(diào)用遠(yuǎn)程服務(wù)器上的對(duì)象,使Java編程人員能夠在網(wǎng)絡(luò)環(huán)境中分布操作。 創(chuàng)建一個(gè)簡(jiǎn)單的Java分布式遠(yuǎn)程方法調(diào)用程序可以按以下幾個(gè)步驟操作, 一、定義遠(yuǎn)程接口: 在 Java 中,遠(yuǎn)程對(duì)象是實(shí)現(xiàn)遠(yuǎn)程接口的類(lèi)的實(shí)例, 遠(yuǎn)程接口聲明每個(gè)要遠(yuǎn)程調(diào)用的方法。在需要?jiǎng)?chuàng)建一個(gè)遠(yuǎn)程對(duì)象的時(shí)候,我們通過(guò)傳遞一個(gè)接口來(lái)隱藏基層的實(shí)施細(xì)節(jié),客戶通過(guò)接口句柄發(fā)送消息即可。 遠(yuǎn)程接口具有如下特點(diǎn): 1) 遠(yuǎn)程接口必須為public屬性。如果不這樣,除非客戶端與遠(yuǎn)程接口在同一個(gè)包內(nèi),否則 當(dāng)試圖裝入實(shí)現(xiàn)該遠(yuǎn)程接口的遠(yuǎn)程對(duì)象時(shí),調(diào)用會(huì)得到錯(cuò)誤結(jié)果。 2) 遠(yuǎn)程接口必須擴(kuò)展接口java.rmi.Remote。 3) 除與應(yīng)用程序本身特定的例外之外,遠(yuǎn)程接口中的每個(gè)方法都必須在自己的throws從句中 聲明java.rmi.RemoteException。(或RemoteException 的父類(lèi))。 4) 作為參數(shù)或返回值傳遞的一個(gè)遠(yuǎn)程對(duì)象(不管是直接,還是本地對(duì)象中嵌入)必須聲明為遠(yuǎn) 程接口,而不應(yīng)聲明為實(shí)施類(lèi)。 下面是遠(yuǎn)程接口的接口RmiSample的定義 Java代碼 import java.rmi.*; public interface RmiSample extends Remote { public int sum(int a,int b) throws RemoteException; } 二、實(shí)現(xiàn)遠(yuǎn)程接口: 遠(yuǎn)程對(duì)象實(shí)現(xiàn)類(lèi)必須擴(kuò)展遠(yuǎn)程對(duì)象java.rmi.UnicastRemoteObject類(lèi),并實(shí)現(xiàn)所定義的遠(yuǎn)程接口。遠(yuǎn)程對(duì)象的實(shí)現(xiàn)類(lèi)中包含實(shí)現(xiàn)每個(gè)遠(yuǎn)程接口所指定的遠(yuǎn)程方法的代碼。這個(gè)類(lèi)也可以含有附加的方法,但客戶只能使用遠(yuǎn)程接口中的方法。因?yàn)榭蛻羰侵赶蚪涌诘囊粋€(gè)句柄,而不是它的哪個(gè)類(lèi)。必須為遠(yuǎn)程對(duì)象定義構(gòu)造函數(shù),即使只準(zhǔn)備定義一個(gè)默認(rèn)構(gòu)造函數(shù),用它調(diào)用基礎(chǔ)類(lèi)構(gòu)造函數(shù)。因?yàn)榛A(chǔ)類(lèi)構(gòu)造函數(shù)可能會(huì)拋出java.rmi.RemoteException,所以即使別無(wú)它用必須拋出java.rmi.RemoteException例外。 以下是遠(yuǎn)程對(duì)象實(shí)現(xiàn)類(lèi)的聲明: Java代碼 import java.rmi.*; importjava.rmi.server.*; public class RmiSampleImpl extends UnicastRemoteObject implements RmiSample { RmiSampleImpl() throws RemoteException { super(); } public int sum(int a,int b) throws RemoteException { return a + b; } } 三、編寫(xiě)服務(wù)器類(lèi): 包含 main 方法的類(lèi)可以是實(shí)現(xiàn)類(lèi)自身,也可以完全是另一個(gè)類(lèi)。下面通過(guò)RmiSampleServer 來(lái)創(chuàng)建一個(gè)遠(yuǎn)程對(duì)象的實(shí)例,并通過(guò)java.rmi.registry.LocateRegistry類(lèi)的createRegistry 方法從指定端口號(hào)啟動(dòng)注冊(cè)服務(wù)程序,也可以通過(guò)執(zhí)行 rmiregistry 命令啟動(dòng)注冊(cè)服務(wù)程序,注冊(cè)服務(wù)程序的缺省運(yùn)行端口為 1099。必須將遠(yuǎn)程對(duì)象名字綁定到對(duì)遠(yuǎn)程對(duì)象的引用上:Naming.rebind("//localhost:8808/SAMPLE-SERVER" , Server); 以下是服務(wù)器類(lèi)的聲明: Java代碼 import java.rmi.*; import java.rmi.registry.*; public class RmiSampleServer{ public static void main(String args[]) { try { LocateRegistry.createRegistry(8808) ; SampleServerImpl Server = new SampleServerImpl(); // 將該對(duì)象實(shí)例與名稱“SAMPLE-SERVER”捆綁 Naming.rebind("//localhost:8808/SAMPLE-SERVER" , Server); } catch (MalformedURLException me) { System.out.println("Malformed URL: " + me.toString()); } catch (RemoteException re) { System.out.println("Remote exception: " + re.toString()); } } } 四、編寫(xiě)使用遠(yuǎn)程服務(wù)的客戶機(jī)類(lèi): 客戶機(jī)類(lèi)的主要功能有兩個(gè),一是通過(guò)Naming.lookup方法來(lái)構(gòu)造注冊(cè)服務(wù)程序stub 程序?qū)嵗?#xff0c;二是調(diào)用服務(wù)器遠(yuǎn)程對(duì)象上的遠(yuǎn)程方法。 以下是服務(wù)器類(lèi)的聲明: Java代碼 import java.rmi.*; importjava.rmi.server.*; public class RmiSampleClient { public static void main(String[] args) { try { String url = "//localhost:8808/SAMPLE-SERVER"; RmiSample RmiObject = (RmiSample)Naming.lookup(url); System.out.println(" 1 + 2 = " + RmiObject.sum(1,2) ); } catch (RemoteException exc) { System.out.println("Error in lookup: " + exc.toString()); } catch (MalformedURLException exc) { System.out.println("Malformed URL: " + exc.toString()); } catch (java.rmi.NotBoundException exc) { System.out.println("NotBound: " + exc.toString()); } } } 五、編譯代碼: 要編譯 Java 源文件,請(qǐng)運(yùn)行javac 命令: Java代碼 javac RmiSample.java RmiSampleImpl.java RmiSampleServer.java RmiSampleClient.java javac RmiSample.java RmiSampleImpl.java RmiSampleServer.java RmiSampleClient.java 六、為遠(yuǎn)程對(duì)象實(shí)現(xiàn)創(chuàng)建根和干: 要?jiǎng)?chuàng)建存根程序和骨架文件,應(yīng)以包含遠(yuǎn)程對(duì)象實(shí)現(xiàn)的已編譯類(lèi)包全名運(yùn)行 rmic編譯器。 存根(Stub)是遠(yuǎn)程對(duì)象在客戶端的代理,它將RMI調(diào)用傳遞給服務(wù)器端的骨架(Skeleton),后者負(fù)責(zé)將該調(diào)用傳遞給實(shí)際的遠(yuǎn)程方法輸入如下: Java代碼 D:\RMI>rmic -d D:\RMI RmiSampleImpl D:\RMI>rmic -d D:\RMI RmiSampleImpl 執(zhí)行這個(gè)命令, 若rmic成功運(yùn)行,RMI目錄下就會(huì)多出兩個(gè)新類(lèi): RmiSampleImpl_Stub.class RmiSampleImpl_Skel.class 它們分別對(duì)應(yīng)的是存根(stub)和骨架(skeleton). 七、運(yùn)行代碼: 運(yùn)行服務(wù)端程序:在Windows下,輸入下列命令,在后臺(tái)啟動(dòng)RmiSampleServer程序: Java代碼 D:\RMI>java RmiSampleServer D:\RMI>java RmiSampleServer 運(yùn)行客戶端程序: Java代碼 D:\RMI>java RmiSampleClient D:\RMI>java RmiSampleClient 客戶端輸出: 1 + 2 = 3總結(jié)
- 上一篇: vscode 编辑器快捷键
- 下一篇: LINUX 内核代码备忘录