使用ICE建立C++與C#的通訊
ICE的優勢是作為通訊中間件可支持跨平台的通訊,目前支持C++、C#、JAVA、Python、Ruby等多種語言。下面通過一個示例,描述怎樣通過ICE建立C++與C#之間的通訊。
一 示例描述
搭建一個簡單的聊天室,服務端使用C++實現,客戶端使用C#實現,中間以ICE構建通訊通道。聊天室實現的功能包括:用戶登錄/注銷、發送消息、接受消息。
二 准備Slice文件
Slice作為ICE本身特有的語言,成為跨平台通訊的橋梁。通過Slice文件描述需要實現的接口,再由ICE提供的各個語言編譯器生成各語言的接口類,各語言分別負責根據接口類實現屬於本身的邏輯細節即可,據說這種思想是從老牌的通訊中間件CORBA中借鑒過來的。
聊天室的Slice文件定義如下:
module Chat { interface Room { bool login(string user, MessageReceiver* receiver); void logout(string user); void sendMessage(string user, string message); }; interface MessageReceiver { void onMessage(string sender, string msg); }; dictionary<string, MessageReceiver*> UserList; };
分析上面的Slice文件如下:
1、 在命名空間為Chat下定義了兩個類(接口),Room和MessageReceiver。
2、 Room主要是Server端實現,Client端調用。實現了登錄、注銷和發送信息的接口函數。
3、 MessageReceiver主要是Client端實現,Server端調用的回調函數接口。這是因為Server端在向Client端發送信息的時候,必須知道Client端的通訊地址。因此需要這個回調函數類。
4、 UserList主要是Server端用來存儲Client端的用戶名及回調函數句柄的。
三 實現Server端
通過Slice2Cpp程序將Slice文件生成ChatRoom.h和ChatRoom.cpp,將兩個文件加入到工程中,同時新建一個類繼承Chat::Room,實現Room的三個虛擬函數接口,這個類被稱為Server端的Servant類。代碼如下:
class ChatRoomI :public Chat::Room { public: ChatRoomI(void); ~ChatRoomI(void); virtual bool login(const ::std::string&, const ::Chat::MessageReceiverPrx&, const ::Ice::Current& ); virtual void logout(const ::std::string&, const ::Ice::Current& ); virtual void sendMessage(const ::std::string&, const ::std::string&, const ::Ice::Current&); private : Chat::UserList _userList; void BroadCast(const ::std::string user,const ::std::string message); bool Notify(const ::std::string& user, const ::std::string& message, const ::Chat::MessageReceiverPrx& receiver); };
注意有兩個私有函數BroadCast和Notify為從Server端廣播消息至Client端時用到的,並沒有什么神秘的地方。示例工程可在文章末尾處下載,具體實現細節略去。
四 實現Client端
使用Slice2CS程序將Slice文件生成ChatRoom.cs文件,將此cs文件添加到一個控制台程序的工程中。新建MsgReceiver類繼承Chat.MessageReceiverDisp_,Chat.MessageReceiverOperations_兩個抽象類,實現onMessage函數。
public override void onMessage(string sender, string msg, Ice.Current current__) { Console.WriteLine(String.Format("{0}:{1}", sender, msg)); }
新建Client類,實現Client端與Server端之間的通訊邏輯,並生成MsgReceiver類的本地代理類,發送到Server端實現發送消息的回調邏輯。
Ice.ObjectAdapter objAdapter = communicator().createObjectAdapterWithEndpoints( "Chat.UserAdapter", "default -h 127.0.0.1 -p 10001"); Ice.Object msgRece = new MsgReceiver(); objAdapter.add(msgRece,communicator().stringToIdentity("Chat.User")); objAdapter.activate(); Chat.MessageReceiverPrx userPrx = Chat.MessageReceiverPrxHelper.uncheckedCast (objAdapter.createProxy(communicator().stringToIdentity("Chat.User")));
示例工程在本文末尾下載。
四 示例截圖
Server端:
Client端:
代碼下載: