ZEROC ICE 跨平台間程序調用 java版


前言:

  本來建博客是為了和大家分享一些前端的開發經驗和心得呢,但是陰差陽錯,第一篇技術博客確實關於跨平台,跨語言服務端調用的解決方案---ZEROC ICE。

     最近一個項目涉及到java、python、C++三種不同語言間的互相調用。經過反復討論決定采取ZEROC來實現,在實現的過程中發現網上的很多資料要么很不完整,要么就是過於基礎,完全不能滿足項目的需要。尤其是對於如何使用ice進行分布式編程介紹更少,除了C++語言外,其他語言的ice使用說明也存在明顯不足,雖然不同語言原理一樣,但是對於初學者而言,要求還是比較高。所以特地在這里對我們的ice實施解決方案做一個回顧與總結,同時也拋磚引玉,如果有高手發現我們的方案不好,讓我也有個二次深入學習的機會!

 

正文:

  本博客系列主要講解  java語言的ice 客戶端、服務端調用、amd服務端異步、客戶端調用等。從hello world開始講解!

  一、寫一個helloworld的ice文件HelloWorld.ice

1 module myHelloWorld{
2     interface HelloWorld{ 3 void say(string s); 4  }; 5 };

  module相當於java中的包名;interface對應java中的接口;say對應方法

  二、編譯這個ice定義

  安裝一個ice服務器,注意如果大家是不同語言合作開發,那么不同人安裝的ice版本最好保持一致,安裝linux版本時,注意各種rpm之間的依賴關系。(這里默認大家都會安裝,如果不會就去百度去吧,官網上有詳盡的說明:https://zeroc.com/)

  通過slice2java HelloWorld.ice   來編譯ice為java包文件。編譯好之后請將改文件夾直接拷貝到工程的src目錄下,因為生成的java文件會有對應的包名。為了不報錯,必須實際路徑和包名一致。同時,到ice的安裝目錄下,打來lib文件夾,將其中的jar包引入到工程中,確保相關文件沒有報錯即可。

   三、編寫Servant類

  servant類是ice所定義的接口,在服務器端的實現類。我們在該類中可以編寫服務器端對請求的具體處理。

  按照管理,servant類名是ice接口名加一個“I”后綴,如下:

 1 package client;
 2 
 3 import Ice.Current; 4 import myHelloWorld._HelloWorldDisp; 5 6 public class HelloWorldI extends _HelloWorldDisp{ 7 8 private static final long serialVersionUID = 1L; 9 10  @Override 11 public void say(String s, Current __current) { 12 System.out.println("Hello World!"+" the string s is " + s); 13  } 14 }

  四、創建遠程的服務器類

  初學者建議仔細看看下邊的server服務類,該服務類絕大多數代碼都是固定格式,只需要根據自己的實際情況變更一下端口、servant的名稱、需要加入服務器的servant類即可。

 1 package client;
 2 public class Server { 3 4 public static void main(String[] args) 5  { 6 int status = 0; 7 // Communicator實例,是ice run time的主句柄 8 Ice.Communicator ic = null; 9 try 10  { 11 // 調用Ice.Util.Initialize()初始化Ice run time 12 System.out.println("初始化ice run time..."); 13 ic = Ice.Util.initialize(args); //args參數可傳可不傳 14 15 16 // 創建一個對象適配器,傳入適配器名字和在10000端口處接收來的請求 17 System.out.println("創建對象適配器,監聽端口10000..."); 18 Ice.ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints("SimplePrinterAdapter", "default -p 10000"); 19 20 // 實例化一個PrinterI對象,為Printer接口創建一個servant 21 System.out.println("為接口創建servant..."); 22 Ice.Object object = new HelloWorldI(); 23 24 // 調用適配器的add,告訴它有一個新的servant,傳遞的參數是剛才的servant,這里的“SimplePrinter”是Servant的名字 25 System.out.println("對象適配器加入servant..."); 26 adapter.add(object, Ice.Util.stringToIdentity("SimplePrinter")); 27 28 //調用適配器的activate()方法,激活適配器。被激活后,服務器開始處理來自客戶的請求。 29 System.out.println("激活適配器,服務器等待處理請求..."); 30  adapter.activate(); 31 32 //這個方法掛起發出調用的線程,直到服務器實現終止為止。或我們自己發出一個調用關閉。 33  ic.waitForShutdown(); 34 } catch (Ice.LocalException e) 35  { 36  e.printStackTrace(); 37 status = 1; 38 } catch (Exception e) 39  { 40  e.printStackTrace(); 41 status = 1; 42 } finally 43  { 44 if (ic != null) 45  { 46  ic.destroy(); 47  } 48  } 49  System.exit(status); 50  } 51 }

  五、編寫客戶端類

  與服務端一樣,客戶端的格式也是基本不變的。

package client;
import myHelloWorld.HelloWorldPrx; import myHelloWorld.HelloWorldPrxHelper; public class Client { public static void main(String[] args) { int status = 0; // Communicator實例 Ice.Communicator ic = null; try { // 調用Ice.Util.Initialize()初始化Ice run time ic = Ice.Util.initialize(args); // 根據servant的名稱以及服務器ip、端口獲取遠程服務代理 Ice.ObjectPrx base = ic.stringToProxy("SimplePrinter:default -p 10000"); // 將上面的代理向下轉換成一個Printer接口的代理 HelloWorldPrx helloWorld = HelloWorldPrxHelper.checkedCast(base); // 如果轉換成功 if (helloWorld == null) { throw new Error("Invalid proxy"); } // 調用這個代理,將字符串傳給它 helloWorld.say("bar"); } catch (Ice.LocalException e) { e.printStackTrace(); status = 1; } catch (Exception e) { e.printStackTrace(); status = 1; } finally { if (ic != null) { ic.destroy(); } } System.exit(status); } }

  六、運行

  先運行服務器,服務器線程一直運行等待,如下:

初始化ice run time...
創建對象適配器,監聽端口10000...
為接口創建servant...
對象適配器加入servant...
激活適配器,服務器等待處理請求...

  運行了客戶端后,顯示如下:

初始化ice run time...
創建對象適配器,監聽端口10000...
為接口創建servant...
對象適配器加入servant...
激活適配器,服務器等待處理請求...
Hello World! the string s is bar

  七、小結

  以上的代碼是同一台電腦之間調用,如果需要跨服務器之間調用,或者無論其他什么語言的客戶端調用,只需要獲取遠程服務代理的時候加上ip即可。default默認采取tcp協議,所以下邊的代碼其實等同於上邊我們調用本地機器的代碼。

Ice.ObjectPrx base = ic.stringToProxy("SimplePrinter:tcp -h 127.0.0.1 -p 10000");

 

  上邊是最簡單的ice調用,它的優勢是:在我們編寫服務端客戶端的時候,不需要考慮調用方是什么語言編寫的,只需要按照我們當前使用語言的書寫習慣去完成我們自己一端的代碼即可,並且服務器客戶端之間可以通過結構體(對象)的方式進行直接調用,更符合我們的日常變成習慣。

   下一節我會把如何ice amd調用的原理以及如何通過java語言編寫ice服務端、客戶端的代碼分享出來,后邊可能還會有如何通過ice建立長連接,實現服務器客戶端的互相調用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM