1. 書目
精通RMI——Java與EJB企業(yè)級應(yīng)用開發(fā)
Java™ RemoteMethodInvocation Specification
Java tutorial- RMI
2. 基礎(chǔ)知識
2.1 網(wǎng)絡(luò)通信協(xié)議
網(wǎng)絡(luò)通信層是分布式計算環(huán)境中使用客戶/服務(wù)器結(jié)構(gòu)的一個核心技術(shù),而網(wǎng)絡(luò)編程中大體有兩種通信模式,無連接和面向連接的協(xié)議。
UDP
UDP (universal datagram protocol)是一種用于無連接通信的標準化協(xié)議,其建立在IP協(xié)議之上,而IP協(xié)議是internet使用的基本數(shù)據(jù)傳輸協(xié)議。UDP協(xié)議的主要作用是將網(wǎng)絡(luò)數(shù)據(jù)流量壓縮成數(shù)據(jù)報文的形式。一個典型的數(shù)據(jù)報文就是一個二進制數(shù)據(jù)的傳輸單位。每一個數(shù)據(jù)報的前8個字節(jié)用來包含報頭信息,剩余字節(jié)則用來包含具體的傳輸數(shù)據(jù)。UDP協(xié)議并不提供數(shù)據(jù)傳送的保證機制。如果在從發(fā)送方到接收方的傳遞過程中出現(xiàn)數(shù)據(jù)報的丟失,協(xié)議本身并不能做出任何檢測或提示。因此,通常人們把UDP協(xié)議稱為不可靠的傳輸協(xié)議。一般用來傳輸少量數(shù)據(jù),它資源消耗小,處理速度快。
TCP
TCP(transport control protocol)傳輸控制協(xié)議,標準化的面向連接的通信協(xié)議。在使用TCP協(xié)議中發(fā)送者和接收者必須在通信之前建立連接,連接建立之后被看成是一個數(shù)據(jù)流,發(fā)送者將數(shù)據(jù)發(fā)到該數(shù)據(jù)流上,接收者從該數(shù)據(jù)流上讀取數(shù)據(jù)。如果接收者也同時是發(fā)送者則連接是雙向的。通信完成后任何一方都可以關(guān)閉連接,之后的讀寫操作都會失敗。TCP協(xié)議提供了可靠的面向?qū)ο蟮臄?shù)據(jù)流傳輸服務(wù)的規(guī)則和約定。簡單的說在TCP模式中,對方發(fā)一個數(shù)據(jù)包給你,你要發(fā)一個確認數(shù)據(jù)包給對方。Java提供的類庫都將TCP/IP協(xié)議的使用借助套接字(Socket)進行了抽象。套接字包含了建立與遠程主機的連接,與主機進行通信以及關(guān)閉連接所需要的所有操作,而這些操作實際上還是由TCP/IP來執(zhí)行的。
編組
在應(yīng)用復雜尤其是面向?qū)ο蟮臅r候,一方面會遇到處理數(shù)據(jù)或者對象的結(jié)構(gòu)的問題。另一方面還會遇到面向流的用來發(fā)送字節(jié)或字符塊的網(wǎng)絡(luò)連接問題。此時需要將對象轉(zhuǎn)換成連接可以處理的格式,從而使自定義的對象可以通過連接管道。
編組(marshalling)是一個將負責對象轉(zhuǎn)換成字節(jié)流的過程,然后在使用反過程----反編組將字節(jié)流轉(zhuǎn)換成對象。Java中編組的實現(xiàn)方式是序列化(serialization)。

代理
代理是一個實現(xiàn)給定接口的對象,但是不直接執(zhí)行一些代碼計算結(jié)果,而是代表其他一些對象執(zhí)行實際計算的對象。

代理可以代表其他的庫或者某種類似的可以代替它執(zhí)行網(wǎng)絡(luò)通信的東西。這就是RMI工作的原理,代理在RMI也即存根(Stub)。
引用位于服務(wù)器中的對象的代理是如何構(gòu)造的?客戶端不能有一個真的Java引用,因為Java引用只在對象位于同一個JVM時才能正常工作。構(gòu)造的基本思想是為服務(wù)器對象分配一個唯一的標識序號,該序號由代理保存,此外還有對象所在的主機名。

客戶如何請求代理
在獲取代理時我們需要一個間接層把所有細節(jié)抽象,通過使用名字去獲得對應(yīng)對象的思想就是命名。命名的一個主要作用是通過使用對象的名字,簡化獲得對象的任務(wù)。
對于RMI來說,最通用的命名實現(xiàn)時RMI注冊,它具有bind和lookup操作,對于命名服務(wù)來說,客戶端其實存在一個它的代理。
命名使用示例圖
