近期评论

    今日最热

    No top posts yet

    S60中使用CS结构实现事件(消息)驱动的简单方法

    C/S结构的进程间通信机制可谓Symbian平台的一大特色,使用此结构相应的一系列API可以方便地实现安全的进程间通信。很多时候,Client和Server的互动需要使用事件(消息)驱动的方式来进行,事实上,很多系统Server如Message Server等都提供此类的功能。在自己编写的程序中如何实现这种功能的问题困扰了我一段时间,因为本身支持C/S结构的API(RSessionBase等)并不支持这样的工作方式(还是实际上支持而我不知道?当然我也不敢自认专家),最后我采用了一种自创(不一定新颖)的方法来实现了这个功能。

    一、定义一个接口类如MObserver,使其包含事件相应的处理函数的定义,如
    class MObserver
    {
    BOOL virtual HandleEvent( TEvent &aEvent) = 0;
    };

    二、定义一个活动对象会话类(继承自RSessionBase和CActive)如RMySession,正常地包含连接Server和通信的功能,同时让RMySession(可以在构造函数中)接收一个指向MObserver的指针,这样就能在事件发生时调用接口函数来处理事件了。
    class RMySession : public RSessionBase, public CActive

    {
    public:

    ~RMySession ();
    static RMySession * NewL( MObserver *aObserver);
    static RMySession * NewLC( MObserver *aObserver);

    private:
    RMySession ();
    void ConstructL( MObserver *aObserver);

    MObserver* iObserver;
    };

    void RMySession::ConstructL( MObserver *aObserver)
    {
    iObserver = aObserver;
    }

    三、定义一种消息类型如TEvent,用于在Server和Client之间传递事件的信息。在RMySession添加一个TEvent的实例用于接收来自Server的消息。
    class TEvent
    {

    };

    class RMySession
    {

    private:
    TEvent iEvent;
    TPckg< TEvent> iEventPckg;
    };

    RMySession::RMySession : iEventPckg( iEvent)
    {

    };

    四、为RMySession定义两个成员函数StartWaiting和StopWaiting,用于启动和停止对事件的等待。
    void RMySession::StartWaiting()
    {
    iState = EWaiting;
    TIpcArgs p;
    p.Set( 0, iEventPckg);
    SendReceive( EStartWaiting, p, iStatus);
    SetActive();
    }
    void RMKHSession::DoCancel()
    {
    StopWaiting();
    }
    void RMKHSession::StopWaiting()
    {
    TInt rc;
    TIpcArgs p;
    iState = EStopped;
    rc = SendReceive( EStopWaiting, p);
    }

    五、实现RunL,在其中处理到来的事件。
    RMKHSession::RunL()
    {
    if (iState == EStopped)
    {
    return;
    }
    else if (iState != EError)
    {
    StartWaiting();
    SetActive(); // Tell scheduler a request is active
    iObserver->HandleMKHEvent( iEvent);
    }
    }

    六、在Server端,对于到来的EStartWaiting请求暂时将该RMessage的实例缓存起来,等到事件发生时,再改写其携带的TEvent实例的内容,然后用RMessage::Complete( TInt)将消息传递回Client。
    void CServerSession::ServiceL( const RMessage2 &aMessage)
    {
    switch( aMessage.Function())
    {
    case EStartWaiting:
    {
    iCurMsg = new RMessage2( aMessage);
    }
    break;
    case EStopWaiting:
    {
    if( iCurMsg) iCurMsg->Complete( -1);
    iCurMsg = NULL;
    aMessage.Complete(0);
    }
    break;

    }

    }
    void CServerSession::CompleteMessage( TMKHEvent &aEvent)
    {
    if( iCurMsg)
    {
    TPckg<TMKHEvent> pckg( aEvent);
    iCurMsg->Write(0, pckg, 0);
    iCurMsg->Complete( 0);
    delete iCurMsg;
    iCurMsg = NULL;
    }
    }

    这样,就可以实现简单的C/S结构事件驱动程序。

    完毕。

    Leave a Reply