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!