|
||
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;
};
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;
};
The NewL()
function creates and returns a new
instance of the subsession object. This is called when the client requests the
creation of a new subsession.
The message service functions
Increase()
, IncreaseBy()
etc. respond appropriately
to client requests.
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;
}
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.