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结构事件驱动程序。
完毕。
近期评论