CORBA CORBA是OMG組織針對企業應用上的分布式程序開發標准。重要的一點是CORBA僅僅是個規范。CORBA應用以ORB而知名。市場上已經出現了幾個CORBA產品如VISIBROKE,ORBIX等。JAVAIDL是在JDK1。3及以上版本核心包的另一個應用。 CORBA設計的與平台和語言無關(注:與WEB SERVICE類似),因此CORBA能運行在任何平台上,能應用在任何網絡裡,能用任何支持IDL接口的語言編寫。 和RMI類似,CORBA對象也需要用接口描述說明。但是CORBA接口需要用一種和C++類似的IDL來描述,需要指出的是IDL不是一種程序語言。 CORBA應用起步 開發CORBA應用程序主要有以下幾個步驟: 1 定義IDL接口 2 將IDL轉換成JAVA 3 應用接口 4 開發服務器端 5 開發客護端 6 運行名稱服務器,服務器和客戶程序 我們現在一步一步地講述用CORBA開發文件傳輸的應用,和RMI相似。我們將用到JavaIDL,在JDK1。3包裡有。 定義接口 定義接口的時候,我們需要考慮服務器支持的操作類型。在文件傳輸應用裡,需要用到一個下載文件的方法。例5有了這個接口FileInterface。客戶端將調用這個方法下載文件。 IDL裡的sequence和數組比較接近,但它不是個固定的長度。 注意方法downloadFile的String 參數類型有三種傳輸模式:in(從客戶端到服務器),out(從服務器端到客戶端),inout(雙向) Code Sample 5: FileInterface.idl interface FileInterface { typedef sequence
Data; Data downloadFile(in string fileName); }; 接口定義完成後,你可以用JDK1。3帶的IDLJ編譯器編譯生成JAVA。 Idlj編譯器帶有一些參數,如-f參數 可以生成你指定的客護端代碼或服務端骨干碼,或兩者。在這個例子裡,我們將在兩台機器裡,所以我們用-fserver,-fclient生成服務器端,客戶端JAVA代碼。 下面我們編譯接口生成服務器端代碼,用下面命令: prompt> idlj -fserver FileInterface.idl 這個命令將生成Skeleton,holder,helper和其它類。生成類_FileInterfaceImplBase,我們將利用這個類的接口來實現應用。 應用接口 下面我們將實現下載方法。 Code Sample 6: 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); input.close(); } catch(Exception e) { System.out.println("FileServant Error: "+e.getMessage()); e.printStackTrace(); } return(buffer); } } 服務器端開發 下一步我們開發服務器端。包括以下幾個步驟: 1 初始化ORB 2 創建一個FileServant對象 3 在CORBA名稱服務裡注冊對象名 4 打印一個狀態信息 5 等待客戶端請求 Code Sample 7: FileServer.java import java.io.*; import org.omg.CosNaming.*; import org.omg.CosNaming.NamingContextPackage.*; import org.omg.CORBA.*; public class FileServer { public static void main(String args[]) { try{ // create and initialize the ORB ORB orb = ORB.init(args, null); // create the servant and register it with the ORB FileServant fileRef = new FileServant(); orb.connect(fileRef); // get the root naming context org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService"); NamingContext ncRef = NamingContextHelper.narrow(objRef); // Bind the object reference in naming NameComponent nc = new NameComponent("FileTransfer", " "); NameComponent path[] = {nc}; ncRef.rebind(path, fileRef); System.out.println("Server started...."); // Wait for invocations from clients java.lang.Object sync = new java.lang.Object(); synchronized(sync){ sync.wait(); } } catch(Exception e) { System.err.println("ERROR: " + e.getMessage()); e.printStackTrace(System.out); } } } 一旦FileServer有了ORB(對象請求代理),它就能注冊CORBA服務。它用OMG制定的COS命名服務注冊。它從命名服務根開始,返回一個生成的CORBA對象。為了引用 NamingContext對象,必須narrowed down一個合適的類型。如下做: NamingContext ncRef = NamingContextHelper.narrow(objRef); 對象ncRef object is 現在就是 org.omg.CosNaming.NamingContext 的實例.你可以用它來注冊一個代用綁定方法明明服務的CORBA服務。 開發客戶端 下一步是開發一個客戶端應用,獲得命名服務,訪問和查找別的服務。當得到FileTransfer服務後,就可以調用下載方法了。 Code Sample 8: FileClient import java.io.*; import java.util.*; import org.omg.CosNaming.*; import org.omg.CORBA.*; public class FileClient { public static void main(String argv[]) { try { // create and initialize the ORB ORB orb = ORB.init(argv, null); // get the root naming context org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService"); NamingContext ncRef = NamingContextHelper.narrow(objRef); NameComponent nc = new NameComponent("FileTransfer", " "); // Resolve the object reference in naming NameComponent path[] = {nc}; FileInterfaceOperations fileRef = FileInterfaceHelper.narrow(ncRef.resolve(path)); if(argv.length < 1) { System.out.println("Usage: java FileClient filename"); } // save the file File file = new File(argv[0]); byte data[] = fileRef.downloadFile(argv[0]); BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(argv[0])); output.write(data, 0, data.length); output.flush(); output.close(); } catch(Exception e) { System.out.println("FileClient Error: " + e.getMessage()); e.printStackTrace(); } } } 運行應用 最後一步是運行應用。有幾個步驟: 1 運行CORBA命名服務。用命令tnameserv.來做。卻省端口是900,如果900不能用,你可以用另一端口2500,命令如下: prompt> tnameserv -ORBinitialPort 2500 2 運行服務器 當在卻省端口時 prompt> java FileServer 當在其它端口如2500時 prompt> java FileServer -ORBInitialPort 2500 3 生成客戶端干碼 prompt> idlj -fclient FileInterface.idl 4 運行客戶端,假設在2500端口 prompt> java FileClient hello.txt -ORBInitialPort 2500 hello.txt是要下載的文件 如果命名服務在4500端口 prompt> java FileClient hello.txt -ORBInitialHost gosling -ORBInitialPort 4500 我們還可以在ORB初始化指定一些參數:如 ORB orb = ORB.init(argv, null); 指定CORBA服務器,和命名端口如下: Properties props = new PropertIEs(); props.put("org.omg.CORBA.ORBInitialHost", "gosling"); props.put("orb.omg.CORBA.ORBInitialPort", "2500"); ORB orb = ORB.init(args, props); 測試 在文件傳輸應用中,客戶端需要先知道要傳輸文件的名字,服務器端沒有列表顯示文件名的方法,你可以增加方法擴展應用。當然,你也可以開發UI客戶端代替命令行。當客戶端啟動後,它調用服務器端的方法顯示文件列表,就可以讓用戶選擇文件來下載它。如下圖: Figure 1: GUI-based File Transfer ClIEnt CORBA和RMI比較 顯而易見,RMI比CORBA簡單,開發者不需要熟悉IDL。通常,CORBA與RMI有下列不同: 接口定義不同,CORBA用IDL,而RMI用Java。 CORBA的參數有輸入,輸出類型。 CORBA設計與語言無關。是不同語言開發系統的橋梁。 CORBA對象不能垃圾收集。象我們提到的那樣,CORBA與語言無關。象C++不支持垃圾收集那樣。這是CORBA的缺點。一旦我們創建CORBA對象,它將一直存在,知道你親自去處它。而RMI是自動收集。 結論我們可以用RMI和CORBA開發分布式應用。它們在第一步定義對象接口很接近。 開發系統RMI和CORBA中做選擇其一取決於項目需要。我希望這篇文章能給你開發分布式應用的信息並能在選擇分布式架構時能給你些參考。 翻譯不當之處,請大家批評指正,謝謝! My mail:[email protected]