winston 发表于 2012-1-29 09:35:45

libjingle源码解析(1)--从libjingle里能借鉴什么?



最近无聊,翻了翻开源代码,发现libjingle是个好东西,决定研究研究。
下载地址:
http://code.google.com/p/libjingle/

可以用SVN checkout:
svn checkout http://libjingle.googlecode.com/svn/trunk/ libjingle-read-only
我是用MyJingle来调试的:
http://www.bluehands.de/software/beat/myjingle/

通过MyJingle来调试有如下优点:
1.MyJingle已经帮我们配置好了VC Solution以及Setup打包工程。
2.MyJingle能够连接到Google Talk,这样可以通过Gmail账号连接到google服务器,不用自己搭建XMPP服务器。
3.通过活生生的实例代码,可以编调试,编了解LibJingle的实现方式和XMPP协议。


通过这两天分析Libjingle源代码,了解到如下几点可以借鉴到我们自己的代码中:

1.Signal-Slot机制(这里有相关介绍:http://blog.csdn.net/smallcraft/article/details/2237802)
sigslot简单说,signal是事件源,而slot是事件处理方法,sigslot机制通过弱耦合的方式把属于两个类对象的事件源和事件处理方法联系起来的。
在LibJIngle里的sigslot的用法如下:
首先定义事件源,即XmppClient类,包含类型为sigslog::signal1<XmppEngine::State>的成员变量SignalStateChange,这里的XmppEngine::State模版类型的功能等会介绍一下。

class XmppClient
{
public:
    sigslot::signal1<XmppEngine::State> SignalStateChange;
}
其次定义另一个类事件处理方法,即TestClient,继承自sigslog::has_slots<>(表示这个类具有事件处理功能)。
然后通过刚才定义的XmppClient对象的成员变量SignalStateChange的connect方法把SignalStateChange事件和TestClient的方法OnstateChange联系起来。SignalStateChange一触发,OnstateChange方法就被立即调用。class TestClient: public sigslot::has_slots<>

{
            TestClient(buzz::XmppClient* xmpp_client):xmpp_client_(xmpp_client)
        {
                xmpp_client_->SignalStateChange.connect(this, &TestClient::OnStateChange);
      }
        void OnStateChange(buzz::XmppEngine::State state)
        {
                if(state == buzz::XmppEngine::STATE_CLOSED)
                {
                        printf("Xmpp Closed\r\n");
                        cricket::Thread::Current()->Stop();
                }
                else
                {
                        switch (state)
                        {
                        case buzz::XmppEngine::STATE_START:
                                printf("Xmpp START\r\n");
                                break;

                        case buzz::XmppEngine::STATE_OPENING:
                                printf("Xmpp OPENING\r\n");
                                break;

                        case buzz::XmppEngine::STATE_OPEN:
                                printf("Xmpp OPENED\r\n");
                                InitPresence();
                                break;
                        }
                }
        }
};

那么怎么触发事件呢?

很简单,在任何一个地方调用如下语句即可:
在XmppClient类方法里:void

XmppClient::EnsureClosed() {
if (!d_->signal_closed_) {
    d_->signal_closed_ = true;
    delivering_signal_ = true;
    SignalStateChange(XmppEngine::STATE_CLOSED);
    delivering_signal_ = false;
}
}
而非XmppClient方法如下:
void
XmppClient::Private::OnStateChange(int state) {
if (state == XmppEngine::STATE_CLOSED) {
    client_->EnsureClosed();
}
else {
    client_->SignalStateChange((XmppEngine::State)state);
}
client_->Wake();
}
从上面两个触发事件可知,上面提到的XmppEngine::State是触发事件的参数,这个参数最终调用到OnstateChange的参数里。这个机制很像windows窗口处理里的SendMessage,而更像是一种广播消息方式,因为sigslot可以支持单源触发,多个方法被调用,即SignalStateChange的connect方法可以调用任意多次。
*此外,在ligjingle的sigslot里最多可支持8个参数。

2.处理同步\异步的多线程处理机制。
如果阅读过Chrome的源代码,我们可以得知Chrome的线程模型全部都是异步的command模式,随处可见PostTask和PostDelayedTask等方法。
在Ligjingle,不仅支持异步模式,而且还支持同步模式,如同windows的窗口消息处理机制,它既有PostMessage,又有SendMessage。

3.当处理网络相关的操作时,大量使用适配器模式。
在计算机编程中,适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。ligjingle需要支持多平台,windows和Linux的套接口使用方法大同小异,但这个小小的差异会导致两者的代码无法彼此适应,所以需要通过adapter来包裹这一层平台相关的代码。除此之外,当支持SSL时,对于windows,libjingle采用的是SChannel ,linux的是OpenSSL。



4.打洞技术。
如下图所示,在NAT内部的计算机之间通信或者具有防火墙的客户端之间通信需要通过RelayServer来打洞。
LibJingle通过XMPP协议很好的支持了打洞,以及P2P传输。
通过XMPP协议,LibJingle打洞,我们可以:
1.多用户语音。
2.多用户视频。
3.多用户文件共享。
4.一对一远程桌面协助。
5.多用户在线音乐流同步。
6.还有很多我们可以做到。
5.了解XMPP以及Gtalk的实现方式
什么事XMPP?(http://baike.baidu.com/view/189676.htm)
XMPP是一种基于XML的协议,它继承了在XML环境中灵活的发展性。因此,基于XMPP的应用具有超强的可扩展性。经过扩展以后的XMPP可以通过发送扩展的信息来处理用户的需求,以及在XMPP的顶端建立如内容发布系统和基于地址的服务等应用程 序。而且,XMPP包含了针对服务器端的软件协议,使之能与另一个进行通话,这使得开发者更容易建立客户应用程序或给一个配好系统添加功能。
Gtalk以及MSN,都可以通过XMPP协议来尽兴聊天。

6.后续,需要更深入地了解XMPP以及LibJingle,如果有志同道合的,可以联系: lihe21327@gmail.com

xray 发表于 2012-1-31 13:31:39

好文,学习!
页: [1]
查看完整版本: libjingle源码解析(1)--从libjingle里能借鉴什么?