Important Concepts(重要概念)
你應該理解libjingle中以下的重要概念:
● Signals (信號)
● Threads and Messages (線程、消息)
● Naming Conventions (命名約定)
● SSL Support (SSL 支持)
● Connections (鏈接)
● Transports, Channels, and Connections (傳輸、通道、鏈接)
● Candidates (協商)
● Data Packets (數據包)
Signals (信號)
libjingle 使用sigslot庫 促進對象間的通信。sigslot是一種framework,它可以把呼叫方(calling member)和任意類實現的接收函數很容易地關聯起來,工作方式就像這樣:
1、 發出呼叫的類聲明一個數據成員(被稱作信號),聲明方式使用一種很像模板的語法。這個信號數據成員定義了和接收函數一致的參數。(注:這個接收函數當然是屬于某個類了)
2、 類中的接收函數在實現時,它的參數必須與它關聯的信號的參數相同,這里的參數相同是指數量相同,類型相同和次序相同。這個接收函數有時被稱作receiver或slot(注意:接收函數可以與信號數據成員同屬一個類)。接收函數不能有返回值(可以是void)。它必須繼承自sigslot::has_slots<>。
3、 通過呼叫信號數據成員的connect函數,使信號數據成員與接收函數關聯起來,呼叫時傳遞兩個參數:一個是接收函數所在類的對象指針,另一個是類中的接收函數的地址。
4、 呼叫方使用信號成員就像是調用它自己的函數一樣,傳遞給與信號成員聲明時一致的參數就可以了。如果調用信號成員成功,則所有與此信號成員關聯的任意類中的接收函數都會被調用。
我們可以把任意數量的信號成員與一個接收函數關系起來。libjingle有時就是把多個信號成員與一個接收函數關聯起來,達到統一處理消息之目的。相反,一些類對象聲明一個信號對象,是為了從一個“信號點”廣播消息(“信號點”語意上講就是一個信號成員對象,此對象關聯了眾多的接收函數,當此信號成員被調用時,這些接收函數都能接收到消息,即這些接收函數都被調用)。當對象(包括信號成員所在對象和傳遞給connect函數的接收函數所屬類對象)被銷毀時,sigslot庫會小心處理取消關聯和引用關系。
下面的代碼示范了sigslot庫的使用方法:
// Class that sends the notification.
class Sender {
// The signal declaration.
// The '2' in the name indicates the number of parameters. Parameter //types
// are declared in the template parameter list.
sigslot::signal2<string message, std::time_t time> SignalDanger;
// When anyone calls Panic(), we will send the SignalDanger signal.
void Panic(){
SignalDanger("Help!", std::time(0));
}
// Listening class. It must inherit sigslot.
class Receiver : public sigslot::has_slots<>{
// Receiver registers to get SignalDanger signals.
// When SignalDanger is sent, it is caught by OnDanger().
// Second parameter gives address of the listener function class definition.
// First parameter points to instance of this class to receive notifications.
Receiver(Sender sender){
sender->SignalDanger.connect(this, &Receiver.OnDanger);
}
// When anyone calls Panic(), Receiver::OnDanger gets the message.
// Notice that the number and type of parameters match
// those in Sender::SignalDanger, and that it doesn't return a value.
void Receiver::OnDanger(string message, std::time_t time){
if(message == "Help!")
{
// Call the police
...
}
}
...
}
Sender 類聲明了一個信號數據成員:
sigslot::signal2<string message, std::time_t time> SignalDanger;
語句中的“<string message, std::time_t time>”聲明了可以與此信號成員關聯的接收函數的參數形式,必須是 void functionName( string,std::time_t )形式。
從Sender類的成員數void Panic()實現中可以看到,使用信號成員的形式就像是在調用一個與信號成員同名的函數SignalDanger("Help!", std::time(0));,參數類型就是聲明信號成員時指定的參數。
Receiver類繼承自sigslot::has_slots<>,它的成員函數就具有了成為“接收函數”的“潛質”。
從Receiver的構造函數可以看出,當Receiver對象創建時,必須向它指定一個信號類(即聲明了信號成員的類)對象作為構建造函數的參數,當然此信號類必須有Receiver定義的操作用到的信號成員的樣式。
一旦Receiver類對象被創建,Sender類中的信號成員就與Receiver類中的OnDanger()函數關聯起來了,只要Sender對象的Panic()被調用,Receiver類對象的OnDanger()就被調用,即接收到來自Sender對象的消息,從而進行處理。
如:
Sender sender;
Receiver receiver(sender);
如果 運行:
sender.Panic();
則
receiver.OnDanger();
被自動調用,在此函數的內部就可以處理來自sender的消息。
實現了信號類與接收類之間的松偶合性。
libjingle庫中的一些類,發送信號給接收函數(即listeners 監聽者,可理解為某個類的接收函數),用來傳遞一些重要事件。比如:當你發出或收到一個鏈接嘗試時,Call::SignalSessionState就會發出通知信號。在應用程序中應該有接收函數與這些信號關聯起來,并且做出適當的行為。
按照libjingle中的約定,在聲明信號數據成員時,名字被冠以“Signal”字符,比如:SignalStateChange,SignalSessionState,SignalSessionCreate。
與這些信號關聯的函數名被冠以“On”,比如:OnPortDestropyed(),OnOutgoingMessage(),OnSendPacket();
關于 sigslot庫的更多內容,請查看sigslot文檔。
若有錯誤,請您指正,thanks!