RMI 協議建立在兩大基礎協議之上:
語法規範採用類似 JLS 2.3 節的符號,控制碼用十六進制字面值表示。應用相關值的非終結符由其 Java 類型定義。
通信格式以 Stream 表示,從客戶端視角:Out 為輸出消息,In 為輸入消息。輸入輸出流成對出現,In 僅需協議確認字節,其他標頭信息(魔數、版本)由流對上下文隱含。
Out: Header Messages HttpMessage
Header: 0x4a 0x52 0x4d 0x49 // "JRMI"
Version Protocol
Version: 0x00 0x01
Protocol: StreamProtocol | SingleOpProtocol | MultiplexProtocol
StreamProtocol: 0x4b
SingleOpProtocol: 0x4c
MultiplexProtocol: 0x4d
Messages: Message Messages | Message
Message: Call | Ping | DgcAck
Call: 0x50 CallData
Ping: 0x52
DgcAck: 0x54 UniqueIdentifier
In: ProtocolAck Returns ProtocolNotSupported HttpReturn
ProtocolAck: 0x4e
ProtocolNotSupported: 0x4f
Returns: Return Returns | Return
Return: ReturnData | PingAck
ReturnData: 0x51 ReturnValue
PingAck: 0x53
CallData: ObjectIdentifier Operation Hash Arguments_opt
ObjectIdentifier: ObjectNumber | UniqueIdentifier
UniqueIdentifier: Number Time Count
Arguments: Value Arguments | Value
Value: Object | Primitive
ReturnValue:
0x01 UniqueIdentifier Value_opt // 正常返回
0x02 UniqueIdentifier Exception // 異常返回
注意:ObjectIdentifier、UniqueIdentifier、EndpointIdentifier 使用自定義 write 方法(非 writeObject),組件數據連續寫入流。
ObjectOutputStream.annotateClass:查詢類加載器獲取 codebase URL,非空則寫入流ObjectInputStream.resolveClass:讀取註解,非空則獲取 URL 類加載器加載類(同 Applet 類加載機制)java.* 包類(接收端必然可用)用於防火牆穿透,URL 兩種形式:
https://<host>:<port>/:直接與 RMI 服務器通訊https://<host>:80/cgi-bin/java-rmi?forward=<port>:調用 CGI 腳本轉發HttpMessage: HttpPostHeader Header Message
HttpReturn: HttpResponseHeader Return
| 符號 | Java 類型 |
|---|---|
| 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 |
目的:允許雙端點均可打開多個全雙工虛擬連接,解決 Applet 環境無法創建 ServerSocket 導出遠程對象的問題。
| 狀態 | 條件 |
|---|---|
| 打開 | 發送/接收 OPEN 且未關閉 |
| 等待關閉 | 發送 CLOSE 但未收到 CLOSE/CLOSEACK |
| 關閉 | 從未打開,或收到 CLOSE/CLOSEACK 且未重新打開 |
第一字節操作碼:
| 值 | 操作 |
|---|---|
| 0xE1 | OPEN |
| 0xE2 | CLOSE |
| 0xE3 | CLOSEACK |
| 0xE4 | REQUEST |
| 0xE5 | TRANSMIT |
1 byte opcode | 2 bytes ID
1 byte opcode | 2 bytes ID
1 byte opcode | 2 bytes ID
1 byte opcode | 2 bytes ID | 4 bytes count
count 字節數據(32 位有符號整數,必須 >0)1 byte opcode | 2 bytes ID | 4 bytes count | count bytes data
count >0 且不超過輸出請求數任何違規或通訊錯誤導致多路復用連接立即關閉:實際連接終止,所有虛擬連接即時關閉,用戶仍可讀取已緩衝數據。