Provides code snippets to help you to implement a server interface with subsessions.
A server side subsession is represented by an instance of a class derived
from CObject
.
The following sections refer to an example server, known as the count server.
The code fragments are taken from the example that can be found at ...\examples\Base\IPC\ClientServer\complex
.
In the example, a server side session is represented by the CSession2
derived
class CCountSession
. The server session can have any number
of subsessions, referred to as counters in the example. The subsessions are
instances of the CCountSubSession
class and these are derived
from CObject
.
Unlike the implementation for a simple server interface, as shown in the
example that can be found at ...\examples\Base\IPC\ClientServer\simple
,
the functions to service client requests, e.g. Increase()
,
are in class CCountSubSession
rather than CCountSession
.
The important points to note are:
the CCountSession
class
contains the object container for all the subsession objects which belong
to this session.
the CCountServer
class
contains the one and only object container index through which all
object containers within the server are produced.
the CCountSession
class
contains an object index through which a handle number can be generated for
the subsession.
The CCountSession
class
is defined as:
class CCountSession : public CSession2 { public: // Create the session static CCountSession* NewL(); public: // Constructor CCountSession(); // Called by client/server framework after // session has been successfully created void CreateL(); // Service request void ServiceL(const RMessage2& aMessage); void DispatchMessageL(const RMessage2& aMessage); // Creates new subsession void NewCounterL(const RMessage2& aMessage); // Closes the session void CloseSession(); // Gets the number of resources (i.e. CCountSubSession objects) void NumResources(const RMessage2& aMessage); // Utility to return the CCountSubSession (subsession) object CCountSubSession* CounterFromHandle(const RMessage2& aMessage,TInt aHandle); // Delete the subsession object through its handle. void DeleteCounter(TInt aHandle); // Gets the number of server-side subsession objects. TInt CountResources(); // Panics client void PanicClient(const RMessage2& aMessage,TInt aPanic) const; private: // Object container for this session. CObjectCon *iContainer; // Object index which stores objects // (CCountSubSession instances) for this session. CObjectIx* iCountersObjectIndex; // Total number of resources. In this example // a resource is just the number of CCountSubSession objects. TInt iResourceCount; };
Notes
The data member iCountersObjectIndex
is
a pointer to an object index. Once a subsession object has been created
and stored in its object container, it is then added to the object
index to generate a unique handle number for the counter (subsession
object).
The CCounterFromHandle()
function
returns the subsession object corresponding to a specified handle number.
The NewCounterL()
function
creates a new subsession object.
The DeleteCounter()
function
deletes a subsession object. This is called when the client program requests
to close a subsession.
The CCountSubSession
class
which represents the subsession is defined as:
class CCountSubSession : public CObject { public: // creates a new CCountSubSession object. static CCountSubSession* NewL(CCountSession* aSession); public: CCountSubSession(CCountSession* aSession); void ConstructL(CCountSession* aSession); void SetFromStringL(const RMessage2& aMessage); void Increase(); void IncreaseBy(const RMessage2& aMessage); void Decrease(); void DecreaseBy(const RMessage2& aMessage); void Reset(); void CounterValue(const RMessage2& aMessage); protected: // The session that owns this CCountSubSession object. CCountSession* iSession; private: // The counter value TInt iCount; };
Notes
Subsession requests are handled in a similar way to session requests.
A subsession request
is initially handled by the associated session, i.e. it is passed to the appropriate CSession2::ServiceL()
.
void CCountSession::ServiceL(const RMessage2& aMessage) { TRAPD(err,DispatchMessageL(aMessage)); aMessage.Complete(err); }
The appropriate service function is called via DispatchMessageL()
and
the asynchronous request is completed with aMessage.Complete()
.
This applies to messages targeted at sessions and subsessions.
DispatchMessageL()
The following code fragment shows important parts of this function:
void CCountSession::DispatchMessageL(const RMessage2& aMessage) { // First check for session-relative requests switch (aMessage.Function()) { case ECountServCreateSubSession:// Request to create a subsession NewCounterL(aMessage); return; case ECountServCloseSession: // Request to delete a subsession CloseSession(); return; ... } ... // Must be a subsession request // Find out Which subsession and // forward the request to it. CCountSubSession* counter=CounterFromHandle(aMessage,aMessage.Int3()) switch (aMessage.Function()) { ... case ECountServValue: counter->CounterValue(aMessage); return; default: PanicClient(EBadRequest); return; } }
CCountSubSession* CCountSession::CounterFromHandle(const RMessage2& aMessage,TInt aHandle) { CCountSubSession* counter = (CCountSubSession*)iCountersObjectIndex->At(aHandle); if (counter == NULL) { PanicClient(aMessage, EBadSubsessionHandle); } return counter; }
Notes
The function first checks for messages which are specific to a session and this includes those requests to create and delete a subsession.
After deciding that
messages must be forwarded to a subsession, the function uses the handle number
supplied through the fourth parameter in the message argument array and the CounterFromHandle()
function
to retrieve the appropriate subsession object.
It then invokes the appropriate message service function on that subsession to deal with the client request.
The At()
function
is provided by the CObject
base class.