節(jié)譯,原文地址:
http://www.zeroc.com/articles/index.html需求
1)一個典型的聊天室應(yīng)用,使用客戶器/服務(wù)器架構(gòu),客戶發(fā)送消息到中心服務(wù)器,然后,消息發(fā)送給其它客戶。
2)盡量減少服務(wù)器管理,甚至可以不需要。
3)通信必須安全,通過公共網(wǎng)絡(luò)時必須要保護(hù)個人隱私。
4)當(dāng)客戶端和服務(wù)器有防火墻保護(hù)時也能正常運(yùn)行,客戶端不用修改它的網(wǎng)絡(luò)或者防火墻設(shè)置。
5)客戶端可以在各種平臺上利用多種語言實(shí)現(xiàn),比如說利用Web瀏覽器作為客戶端。
6)客戶端可能網(wǎng)絡(luò)帶寬有限,所以應(yīng)該盡量減少網(wǎng)絡(luò)流量。
只支持單個聊天室。(多個聊天室只是代碼多了點(diǎn),并沒有增加任何難度)。
設(shè)計
在本文中,將會演示多種客戶端的設(shè)計和實(shí)現(xiàn)。包括:
1)C++命令行客戶端;
2)JAVA SWing GUI客戶端;
3).NET WPF客戶端;
4)PHP網(wǎng)頁客戶端;
5)Silverlight 網(wǎng)頁客戶端;
注意,對于ICE3.3, PHP和Ruby只提供了客戶端的Run Time。我們在考慮當(dāng)連接的客戶如何從服務(wù)器獲得消息時,必須要想到這一點(diǎn)。對于消息發(fā)布,有兩種通信模型:
1)推模型:略
2)拉模型:略
推模型比較簡單,容易實(shí)現(xiàn),我們的Chat 客戶端中,C++,Java, .Net, Silverlight(0.3)都使用該模型。PHP客戶端使用拉模型。
推模型定義
每個客戶端中提供一個 ChatRoomCallback 類型的ICE對象到服務(wù)器。當(dāng)發(fā)生事件時,服務(wù)器調(diào)用該對象的操作通知客戶。SLICE定義如下:
// Slice
module Chat
{
// Implemented by clients
interface ChatRoomCallback
{
["ami"] void init(Ice::StringSeq users);
["ami"] void join(long timestamp, string name);
["ami"] void leave(long timestamp, string name);
["ami"] void send(long timestamp, string name, string message);
};
};
1)當(dāng)用戶首次連接到聊天室時,服務(wù)器調(diào)用 init 操作. users參數(shù)告訴用戶目前連接到聊天室的所有用戶信息。
2)有用戶連接到聊天室時,服務(wù)器調(diào)用 join 操作。
3)有用戶斷開連接時,服務(wù)器調(diào)用 leave 操作。
4)有用戶發(fā)送消息時,服務(wù)器調(diào)用 send 操作。
注意設(shè)計使用異步事件。元數(shù)據(jù)指令 ["ami"] 標(biāo)明服務(wù)器異步調(diào)用回調(diào)操作。當(dāng)客戶端行為異常時,這對服務(wù)器是一個保護(hù):客戶端可能長時間阻塞,服務(wù)器調(diào)用期間不會因此失去對線程的控制。
與防火墻協(xié)作
略......
Glacer2是ICE針對這種情況的預(yù)建的解決方案,它扮演一個服務(wù)器前端。Glacer2具有以下特征:
1)支持會話概念,API支持認(rèn)證機(jī)制,可實(shí)現(xiàn)自定義的會話創(chuàng)建和認(rèn)證。
2)單個Glacer2可進(jìn)行任意數(shù)量的服務(wù)器和客戶端轉(zhuǎn)發(fā)。服務(wù)器只要有一個端口接受外來連接,而不用管具體服務(wù)器個數(shù)。
3)對于具有防火墻的客戶端,服務(wù)器也可調(diào)用其提供的回調(diào)。
因?yàn)?Glacer2會話概念是面向連接的,只有當(dāng)客戶端同Glacer2的連接打開時,更精確的說,同Glacer2保持一個激活的會話時,服務(wù)器才可以對客戶進(jìn)行回調(diào)。換句話說,當(dāng)客戶端同Glacer2失去連接,Glacer2自動銷毀會話。為了阻止客戶端到Glacer2的連接被意外關(guān)閉,客戶端必須要禁用ACM(Automic Connection Management, 自動連接管理)。而且,Glacer2通常對長時間空閑的會話設(shè)置超時。當(dāng)聊天室長時間沒有動作時,為了防止Glacer2銷毀會話,客戶端必須周期性進(jìn)行激活,比如,調(diào)用 ice_ping, 來對Glacer2的會話超時進(jìn)行重置。
Chat客戶端通過服務(wù)器提供的 ChatSession接口來和服務(wù)器通信。 ChatSession 從Glacer2::Session派生。
// Slice
module Chat
{
exception InvalidMessageException
{
string reason;
};
interface ChatSession extends Glacier2::Session
{
void setCallback(ChatRoomCallback* cb);
["ami"] long send(string message) throws InvalidMessageException;
};
};
這就是推模型,Chat客戶端調(diào)用ChatSession的send來發(fā)送消息,服務(wù)器調(diào)用每一個客戶的ChatRoomCallback的send操作進(jìn)行分發(fā)。
拉模型定義
TODO