程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> J2EE >> RMI規范--十

RMI規范--十

編輯:J2EE
RMI 通信協議 10.1 概述 RMI 協議使用另兩個協議作為其在通信格式:Java 對象序列化和 HTTP。對象序 列化協議用於編組調用和返回數據。HTTP 協議用於“投寄”遠程方法調用,並在 情況允許時獲得返回數據。每種協議都有專門的語法文檔。產品規則中的非終結 符號可能會引用其它協議(對象序列化或 HTTP)所管理的規則。在跨協議邊界時 ,後續產品將使用該嵌入的協議。 關於語法符號的說明 我們使用與 Java 語言規范(參見 JLS 的第 2.3 節)中類似的符號。 流中的控制代碼由十六進制形式的文字值表示。 語法中的有些非終結符號表示調用中提供的與應用程序有關的值。這種非終結符 號的定義由其 Java 類型組成。語法後面是將這些非終結字符映射到相應類型的 表。 10.2 RMI 傳輸協議 RMI 的通信格式由 Stream 表示。這裡所采用的術語是從客戶機的角度來講的。 out 指輸出消息,而 in 指輸入消息。傳輸標題的內容並未用對象序列化進行格 式化。 Stream: Out In RMI 所用的輸入和輸出流是成對出現的。每個 out 流都有相應的 in 流。在語法 中,out 流映射到套接字的輸出流(從客戶機角度)。in 流(在語法中)將與相 應套接字的輸入流配對。由於輸出與輸入流是成對的,所以輸入流中唯一需要的 標題信息就是一個表示是否理解協議的確認;其他標題信息(例如魔數和版本號 )都將由流對的上下文所隱含。 10.2.1 輸出流格式 RMI 中的輸出流由傳輸標題信息後跟一個消息序列組成。此外,輸出流也可包含 嵌入在 HTTP 協議中的調用。

Out: Header Messages HttpMessage 

Header: 0x4a 0x52 0x4d 0x49 Version Protocol 

Version: 0x00 0x01 

Protocol: StreamProtocol SingleOpProtocol MultiplexProtocol 

StreamProtocol: 0x4b 

SingleOpProtocol: 0x4c 

MultiplexProtocol: 0x4d 

Messages: Message Messages Message 

Messages 將包裝在 Protocol 指定的特定協議內。對於 SingleOpProtocol,He ader 的後面可能只有一個 Message,且該 Message 沒有包裝其它數據。Single OpProtocol 用於 HTTP 請求中所嵌入的調用,其中請求和響應都只能為一個。 對於 StreamProtocol 和 MultiplexProtocol,服務器必須用字節 0x4e(表示支 持該協議)和 EndpointIdentifier(包含主機名和端口號,服務器可以看到它們 在被客戶機使用)進行響應。如果由於安全原因而無法執行該操作,客戶機即可 使用該信息來確定其主機名。隨後,客戶機必須用另一個包含接受連接的缺省端 點的 EndpointIdentifIEr 進行響應。對於MultiplexProtocol,服務器可以用它 來標識客戶機。 對於 StreamProtocol,本次端點協商後,將在輸出流上發送 Messages,而不對 數據進行進一步打包。對於 MultiplexProtocol,套接字將連接用作多路復用連 接的具體連接,如第 10.6 節“RMI 的多路復用協議”中所述。在該多路復用連 接上初始化的虛擬連接由一系列 Messages 組成,如下所述。 輸出消息共有三種:Call、Ping 和 DgcAck。Call 將對方法調用進行編碼。Pin g 是一個傳輸級消息,用於測試遠程虛擬機的活動性。DGCAck 是一個對服務器的 分布式垃圾收集器的確認,指示客戶機已經接收到服務器返回值中的遠程對象。


Message: Call Ping DgcAck 

Call: 0x50 CallData 

Ping: 0x52 

DgcAck: 0x54 UniqueIdentifIEr 
10.2.2 輸入流格式 當前輸入信息共有三種:ReturnData、HttpReturn 和 PingAck。ReturnData 是 “正常”RMI 調用的結果。HttpReturn 是 HTTP 協議中嵌入調用的返回結果。P ingAck 是對 Ping 消息的確認。

In: ProtocolAck Returns ProtocolNotSupported HttpReturn 

ProtocolAck: 0x4e 

ProtocolNotSupported: 0x4f 

Returns: Return Returns Return 

Return: ReturnData PingAck 

ReturnData: 0x51 ReturnValue 

PingAck: 0x53 
10.3 RMI 對對象序列化協議的使用 RMI 調用中的調用和返回數據將使用 Java 對象序列化協議進行格式化。每個方 法調用的 CallData 表示為 ObjectIdentifIEr(調用的目標)、Operation(代 表要調用方法的數字)、Hash(檢驗客戶機 stub 與遠程對象 skeleton 是否使 用同一 stub 協議的數字),後跟該調用的零個或多個參數列表。 在 JDK1.1 stub 協議中,Operation 代表方法號(由 rmic 分配),而 Hash 是 stub/skeleton 散列,它是該 stub 的接口散列。在 JDK1.2 stub 協議(利用 帶 -v1.2 選項的 rmic 生成 JDK1.2 stub)中,Operation 的值為 -1 且 Hash 代表了所要調用方法的散列。散列將在“ RemoteRef 接口”一節中介紹。

CallData: ObjectIdentifier Operation Hash Argumentsopt 

ObjectIdentifier: ObjectNumber UniqueIdentifier 

UniqueIdentifIEr: Number Time Count 

Arguments: Value Arguments Value 

Value: Object Primitive 
RMI 調用的 ReturnValue 由指示正常或異常返回的返回代碼、標記返回值的 Un iqueIdentifier(用於在必要時發送 DGCAck)後跟以下返回結果組成:返回的值 或拋出的異常。 ReturnValue: 0x01 UniqueIdentifier Valueopt 0x02 UniqueIdentifier Exc eption ---------------------------------------------------------------------- ---------- 注意 - ObjectIdentifier、UniqueIdentifier 和 EndpointIdentifIEr 並不是 用缺省序列化編寫的,而是各自使用自己的 write 方法(但不是對象序列化所用 的 writeObject 方法);每種標識符的 write 方法都將其組件數據連續添加到 輸出流中。 ---------------------------------------------------------------------- ---------- 10.3.1 類注解和類加載 RMI 分別覆蓋了 ObjectOutputStream 和 ObjectInputStream 的 annotateClas s 和 resolveClass 方法。每個類都用 codebase URL(加載該類的位置)進行注 解。annotateClass 方法中將查詢加載該類的類加載器以得到其 codebase URL。 如果類加載器非空且其 codebase 也為非空,則將使用 ObjectOutputStream.wr iteObject 方法將該 codebase 寫入流中;否則將使用 writeObject 方法將空值 寫入流中。注意:最好不要注解“java”包中的類,因為它們對於接收者來說總 是可用的。 類注解是在序列化恢復期間用 ObjectInputStream.resolveClass 方法解析的。 resolveClass 方法首先用 ObjectInputStream.readObject 方法讀取注解。如果 注解(codebase URL)非空,它就獲得該 URL 的類加載器並試圖加載該類。利用 Java.Net.URLConnection 獲取類字節,即可對該類進行加載(與 web 浏覽器的 applet 類加載器所用的機制相同)。 10.4 RMI 對 HTTP POST 協議的使用 為了通過防火牆調用遠程方法,有些 RMI 調用使用了 HTTP 協議,尤其是 HTTP POST。在傳遞標題中指定的 URL 可以為下列內容之一: http://:/ http://:80/CGI-bin/Java-rmi?forward= 第一個 URL 用於與特定 host 和 port 上的 RMI 服務器直接通信。第二種形式 的 URL 用於調用服務器上的“CGI”腳本,後者將把調用轉發給指定 port 上的 服務器。 HttpPostHeader 是 POST 請求的標准 HTTP 標題。HttpResponseHeader 是對傳 遞過程的標准 HTTP 響應。如果響應狀態代碼不是 200,則認為沒有返回值。注 意一個 HTTP POST 請求中只能嵌入一個 RMI 調用。 HttpMessage: HttpPostHeader Header Message HttpReturn: HttpResponseHeader Return ---------------------------------------------------------------------- ---------- 注意 - 只有 SingleOpProtocol 出現在 HttpMessage 的標題中。HttpReturn 不 包含用於確認協議的字節。 ---------------------------------------------------------------------- ---------- 10.5 RMI 的與應用程序有關的值 本表列表出 RMI 所用的代表與應用程序有關的值的非終結符號。該表將每個符號 映射為相應的類型。每個符號都分別使用它所嵌入在其中的協議進行格式化。

Count short 

Exception java.lang.Exception 

Hash long 

Hostname UTF 

Number int 

Object Java.lang.Object 

ObjectNumber long 

Operation int 

PortNumber int 

Primitive byte, int, short, long... 

Time long 

10.6 RMI 的多路復用協議 多路復用的目的是提供一種模型,其中兩個端點都可打開多個到另一端點的全雙 工連接,而在相同環境下,使用其他工具(例如 TCP 連接)時,只有一個端點能 打開這樣的雙向連接。利用這種簡單的多路復用協議,RMI 即可允許客戶在某些 其他協議無能為力的情況下,連接到 RMI 的服務器對象上。例如,有些 applet 環境的安全管理器不允許創建服務器套接字監聽到來的連接,以防止這種 appl et 從直接套接字連接上導出 RMI 對象及提供遠程調用服務。但是,如果該 app let 可以打開到其 codebase 主機的正常套接字連接,它就可以在該連接上使用 多路復用協議,從而允許 codebase 主機調用該 applet 所導出的 RMI 對象的方 法。本節介紹了多路復用協議的格式和規則。 10.6.1 定義 本節定義一些將在協議其余部分使用的術語。 端點是用多路復用協議連接的兩個用戶之一。 多路復用協議必須位於已有的雙向可靠字節流之上,假設由一個端點向另一個端 點進行初始化。在當前的 RMI 用法中,它通常是 TCP 連接,由 Java.Net.Sock et 對象建立。該連接稱為具體連接。 多路復用協議有助於虛擬連接的使用。虛擬連接本身就是雙向的可靠字節流,代 表兩個端點之間的特定會話。一個連接上兩個端點之間的虛擬連接集組成一個多 路復用連接。使用多路復用協議,虛擬連接可以由任一端點打開和關閉。虛擬連 接相對給定端點的狀態由在具體連接上發送和接收的多路復用協議元素定義。該 狀態涉及連接是打開還是關閉、傳送的實際數據及相關的流控制機制。如果沒有 特別說明,本節中其余部分將使用術語連接表示虛擬連接。 給定多路復用連接內的虛擬連接由一個 16 位整數標識,稱為連接標識符。因而 ,一個多路復用連接中可能存在 65,536 個虛擬連接。實現可能會限制能同時使 用的虛擬連接數。 10.6.2 連接狀態和流控制 連接由用多路復用協議定義的各種操作來控制。下面是協議所定義的操作名:OP EN、CLOSE、CLOSEACK、REQUEST 和 TRANSMIT。所有操作的准確格式和規則將在 第 10.6.3 節 “協議格式”中詳細介紹。 OPEN、CLOSE 和 CLOSEACK 操作控制連接的打開和關閉,而 REQUEST 和 TRANSM IT 操作用於在流控制機制的限制內在打開的連接上傳輸數據。 連接狀態 如果端點發送連接的 OPEN 操作或接收到連接的 OPEN 操作(且隨後沒有關閉它 ),則該虛擬連接相對於該端點即為打開的。下面介紹不同的協議操作。 如果端點發送連接的 CLOSE 操作,但隨後沒有接收到該連接的 CLOSE 或 CLOSE ACK 操作,則該虛擬連接相對於該端點是等待關閉的。 如果端點從來沒有打開過連接或接收到連接的 CLOSE 或 CLOSEACK 操作(且隨後 沒有打開),則該虛擬連接相對於該端點是關閉的。 流控制 多路復用協議使用簡單的包流控制機制允許多個虛擬連接並存於同一具體連接上 。流控制機制的高級要求是所有虛擬連接的狀態都是獨立的;一個連接的狀態不 會影響其他連接。例如,如果處理來自某個連接的數據的數據緩沖區已滿,應不 會防礙其他連接的數據傳輸和處理。如果連接的繼續依賴於另一個連接的結束( 例如遞歸 RMI 調用時),則這一點將至關重要。因而,它的實際意義是實現必須 總能消耗和處理在具體連接上(假定它遵循該規范)准備輸入的所有多路復用協 議數據。 每個端點具有兩個與各連接相關聯的狀態值:該端點已經請求但尚未接收到的數 據字節數(輸入請求數)和另一端點請求但該端點尚未提供的數據字節數(輸出 請求數)。 端點的輸出請求數在從其他端點接收到 REQUEST 操作時將增大,而在它發送 TR ANSMIT 操作時將減小。端點的輸入請求數在它發送 REQUEST 操作時將增大,而 在它接收到 TRANSMIT 操作時將減小。這些值如果為負就將違反協議。 如果端點發送 REQUEST 操作而導致其輸入請求數增大並超過其當前可以無阻塞處 理的字節數,則違反協議。但如果連接的用戶在等待讀取數據,則應確保其輸入 請求數大於零。 如果端點發送的 TRANSMIT 操作包含有比其輸出請求數更多的字節,則違反協議 。它可以緩沖外流的數據,直到連接用戶請求顯式刷新寫入到連接中的數據。但 如果因為顯式的刷新或實現的輸入緩沖區滿而必須在連接上發送數據,則連接用 戶可能被阻塞,直到有足夠 TRANSMIT 操作。 在滿足上述規則的前提下,實現可以相對自由地發送 REQUEST 和 TRANSMIT 操作 。例如,如果其輸入緩沖區不空,則端點可以請求連接的更多數據。 10.6.3 協議格式 多路復用協議的字節流格式由連續的可變長度記錄序列組成。記錄的第一個字節 是一個操作碼,它可以識別記錄的操作並可確定其內容其余部分的格式。我們定 義了下列合法的操作碼: 值 名稱 0xE1 OPEN 0xE2 CLOSE 0xE3 CLOSEACK 0xE4 REQUEST 0xE5 TRANSMIT 如果記錄的第一個字節不是所定義的操作碼,則違反協議。下面各節介紹了每種 操作碼的記錄格式。 OPEN 操作 下面是 OPEN 操作的記錄格式: 大小(字節) 名字 描述 1 opcode 操作碼 (OPEN) 2 ID 連接標識符 端點將發送 OPEN 操作以打開指定的連接。如果ID 指向對發送端點當前已打開或 即將關閉的連接,則違反協議。打開連接後,連接的輸入和請求數狀態在兩個端 點上都為零。 接收到 OPEN 操作表示另一端點正在打開指定的連接。打開連接後,連接的輸出 和請求數狀態在兩個端點處都為零。 為防止兩端點間的標識符沖突,有效連接標識符空間將根據最高位的值分為兩半 。每個端點僅允許打開高位為某一特定值的連接。啟動具體連接的端點必須只打 開高位為標識符中的連接,另一端點必須只打開高位為零的連接。例如,如果不 能創建服務器套接字的 RMI applet 啟動了與其 codebase 主機的多路復用連接 ,則該 applet 可以打開標識符范圍為 0x8000-7FFF 的虛擬連接,而服務器可以 打開標識符范圍為 0-0x7FFF 的虛擬連接。 CLOSE 操作 以下是 CLOSE 操作的記錄格式: 大小(字節) 名字 描述 1 opcode 操作代碼 (OPEN) 2 ID 連接標識符 端點發送 CLOSE 操作以關閉指定的連接。如果 ID 指向對發送端點當前已關閉或 即將關閉的連接(如果它已發送過此連接的 CLOSE 操作,也可能是對接收端點即 將關閉的連接),則違反協議。 發送 CLOSE 後,連接就成為對發送端點即將關 閉的連接。因此,該端點將不能重新打開該連接,直到它從另一端點接收到 CLO SE 或 CLOSEACK 為止。 接收到 CLOSE 操作表示另一端點已關閉指定的連接,因此該連接已在接收端點上 被關閉。雖然接收端點可能不再為此連接發送其它操作(直到被再次打開),但 它仍應為此連接的讀者提供實現的輸入緩沖區中的數據。如果連接已經被打開( 而不是即將關閉),則接收端點必須用 CLOSEACK 操作作為響應。 CLOSEACK 操作 以下是 CLOSEACK 操作的記錄格式: 大小(字節) 名字 描述 1 opcode 操作代碼 (OPEN) 2 ID 連接標識符 端點發送 CLOSEACK 操作以表明已收到來自接收端點的 CLOSE 操作。如果收到操 作時 ID 指向的連接不是對接收端點將要關閉的連接,則違反協議。 接收到 CLOSEACK 操作可將指定連接的狀態從即將關閉改為已關閉,因此以後還 可重新打開連接。 REQUEST 操作 以下是 REQUEST 操作的記錄格式: 大小(字節) 名字 描述 1 opcode 操作代碼 (OPEN) 2 ID 連接標識符 4 count 請求的額外字節數 端點發送 REQUEST 操作以增大指定連接的輸入請求數。如果 ID 未指向發送端點 打開的連接,則違反協議。端點的輸入請求數按值 count 遞增。count 的值是 32 位有符號整數。如果為負數或零,則違反協議。 接收到 REQUEST 操作將使指定連接的輸出請求數按 count 增加。如果接收端點 即將關閉連接,則將忽略 REQUEST 操作。 TRANSMIT 操作 以下是 TRANSMIT 操作的記錄格式。 大小(字節) 名字 描述 1 opcode 操作碼 (OPEN) 2 ID 連接標識符 4 count 傳輸的字節數 count data 傳輸數據 端點發送 TRANSMIT 操作後,才真正在指定連接上傳輸數據。如果 ID 未指向對 發送端點打開的連接,則違反協議。端點的輸出請求按值 count 遞減。count 的 值是 32 位有符號整數。如果為負數或零,則違反協議。如果 TRANSMIT 操作導 致輸出請求數成為負數,則也違反協議。 接收到 TRANSMIT 操作時從連接中可讀到的字節隊列將增加 count 字節的數據。 接收端點的輸入請求數按值 count 遞減。如果這會使輸入請求數成為零,而該連 接的用戶卻試圖讀取更多數據,則該端點應用另一個 REQUEST 操作作為響應。如 果接收端點即將關閉連接,則將忽略 TRANSMIT 操作。 違反協議 如果出現上述違反協議的現象,或者在具體連接中檢測到通訊錯誤,則多路復用 連接即被關閉。實際連接將被終止,而所有虛擬連接也被立即關閉。連接的用戶 可以讀取虛擬連接中已經可以讀取的數據。
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved