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