CORBA(Common Object Request Broker Architecture)是 OMG 制定的企業級分散式程式開發標準,重點在於它只是一套規範。核心元件是 ORB(Object Request Broker),知名產品包括 VisiBroker、ORBIX 等。Java IDL 是 JDK 1.3 核心套件內建的 CORBA 實作。
CORBA 最大特色是平台無關、語言無關(類似 Web Service),可在任何平台、網路運行,支援所有實作 IDL 介面的語言。與 RMI 類似,CORBA 物件也需以介面描述,但須使用類 C++ 的 IDL(Interface Definition Language)定義,IDL 本身不是程式語言。
檔案傳輸需一個下載方法。IDL 中的 sequence 類似陣列但長度不固定。方法參數有三種傳輸模式:in(客戶端→伺服器)、out(伺服器→客戶端)、inout(雙向)。
// FileInterface.idl
interface FileInterface {
typedef sequence<OCTET> Data;
Data downloadFile(in string fileName);
};
分別產生伺服器端與客戶端骨架:
prompt> idlj -fserver FileInterface.idl
prompt> idlj -fclient FileInterface.idl
伺服器端會產生 _FileInterfaceImplBase 等類別,供實作繼承使用。
// FileServant.java
import java.io.*;
public class FileServant extends _FileInterfaceImplBase {
public byte[] downloadFile(String fileName) {
File file = new File(fileName);
byte[] buffer = new byte[(int)file.length()];
try (BufferedInputStream input = new BufferedInputStream(new FileInputStream(fileName))) {
input.read(buffer, 0, buffer.length);
} catch (Exception e) {
System.out.println("FileServant Error: " + e.getMessage());
e.printStackTrace();
}
return buffer;
}
}
初始化 ORB、建立 Servant、向命名服務註冊、等待請求:
// FileServer.java
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
public class FileServer {
public static void main(String[] args) {
try {
ORB orb = ORB.init(args, null);
FileServant fileRef = new FileServant();
orb.connect(fileRef);
org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
NamingContext ncRef = NamingContextHelper.narrow(objRef);
NameComponent nc = new NameComponent("FileTransfer", "");
NameComponent[] path = {nc};
ncRef.rebind(path, fileRef);
System.out.println("Server started....");
synchronized(new Object()) { wait(); }
} catch (Exception e) {
e.printStackTrace();
}
}
}
取得命名服務、查找遠端物件、呼叫下載方法:
// FileClient.java
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
public class FileClient {
public static void main(String[] argv) {
try {
ORB orb = ORB.init(argv, null);
org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
NamingContext ncRef = NamingContextHelper.narrow(objRef);
NameComponent nc = new NameComponent("FileTransfer", "");
NameComponent[] path = {nc};
FileInterfaceOperations fileRef = FileInterfaceHelper.narrow(ncRef.resolve(path));
if (argv.length < 1) {
System.out.println("Usage: java FileClient filename");
return;
}
byte[] data = fileRef.downloadFile(argv[0]);
try (BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(argv[0]))) {
output.write(data, 0, data.length);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
tnameserv -ORBInitialPort 2500java FileServer -ORBInitialPort 2500idlj -fclient FileInterface.idljava FileClient hello.txt -ORBInitialPort 2500亦可在程式中以 Properties 指定 ORB 參數。
選擇 RMI 或 CORBA 取決於專案需求:純 Java 環境首選 RMI;異構系統整合則 CORBA 更適合。