Using the client server framework

Introduction to how clients interact with servers through a client side API encapsulated in a session. A complex server may also provide subsession classes.

Servers provide access to the resources and services available on the device. Much of the key functionality in Symbian is provided by servers. Examples of servers include the File Server, the Socket Server, and the Window Server. These are all known as system servers because they are started at device boot time and are always running. Symbian also supports transient servers that are started and stopped as client sessions are created and destroyed. From the perspective of the client there is no difference between using a system server and a transient server.

Getting started: creating a session

A server usually runs in a separate process to the client. The server provides a client side API that enables clients to create sessions and send requests to the server. This client side API is packaged as a DLL against which the client code links. For example, to create a Socket Server session the client links against esock.lib and to create a File Server session the client links against efsrv.lib.

All communication with the server is session based. This means that the client must create a session with the server before making any requests. Creating a session involves instantiating the class that encapsulates the client side API and then calling a function to create a session. This function is usually called Open() or Connect(). The client side API is a Symbian R class derived from RSessionBase. This class encapsulates the details of session creation and sending requests to the server.

In summary, the main steps involved in using a server are:
  1. Link against the library file (.lib) that contains the client side API.

  2. Instantiate the class that encapsulates the client side API. This always derives from RSessionBase.

  3. Call the function that creates a session.

  4. Call functions from the client side API that make requests of the server.

  5. Close the session.

What is a session?

The client server framework has three key classes:
  • On the server side there is a server object, derived from CServer2. This is an active object. It is responsible for creating server side sessions and for routing client requests to the correct server side session.

  • Each client that connects with the server is represented on the server side by an instance of an object derived from CSession2.

  • Each client has an RSessionBase derived object. This object is a handle and is derived from RHandleBase. The two session objects communicate via the kernel.

Figure: Main classes of the client server framework

The client side session represents a channel of communication between the client and the server. Access to the server is only possible using the functions provided by the session. These functions hide the details of how data is passed to and from the server and prevent the server from being directly exposed to the client.

Using subsessions

Some servers, especially system servers with rich functionality, provide more than one class as their client side API. In this case using the server typically involves creating both session and subsession objects. For example, to represent a file in the file system it is necessary first to create an RFs object, which is a File Server session, and then an RFile object. The RFile is called a subsession because it makes use of an existing session. This allows you to create several files without incurring the overhead of creating multiple sessions.

You must always create a session before you can use a subsession. The subsession uses the session to communicate with the server. When you open a subsession you pass the session as a parameter in order to associate the session and subsession. Here is an example, with error handling omitted for clarity.

// Create a File Server session object.
RFs fs;

// Connect to the File Server.
// This calls RSessionBase::CreateSession().
fs.Connect();

// Create the subsession that represents an individual file.
RFile file;

// The name of the file to be opened.
_LIT( KDataFileName, “C:\\data\\temp.txt” );

// Open the subsession, passing the session object as the first parameter.
file.Open( fs,KDataFileName );

// Manipulate the file using RFile methods.
...
// Close both the subsession and the session to ensure clean up
// of server resources.
file.Close();
fs.Close();
Some servers do not need to use subsessions. In this case the client interacts with the server using the session object only. Servers make use of subsessions for one of the following reasons:
  • The server functionality consists in multiple logical API groupings, for example file operations and directory operations.

  • To represent multiple objects efficiently, for example multiple files or sockets.

  • To represent objects that are created and destroyed regularly, for example windows.

Client requests may be synchronous or asynchronous

It is up to the server author to provide clients with a meaningful and convenient client side API. In cases where client requests may take a long or unpredictable period to complete, the server should offer asynchronous functions as part of the client side API. For example, the RFile class offers both synchronous and asynchronous overloads of Read() and Write(), as shown below:

class RFile : public RSubSessionBase
  {
public:
  IMPORT_C TInt Open( RFs& aFs, const TDesC& aName, TUint aFileMode );
  IMPORT_C TInt Read( TDes8& aDes ) const;
  IMPORT_C void Read( TDes8& aDes, TRequestStatus& aStatus ) const;
  IMPORT_C TInt Write( const TDesC8& aDes );
  IMPORT_C void Write( const TDesC8& aDes, TRequestStatus& aStatus );
  ...
  };

Asynchronous functions in Symbian always take a TRequestStatus argument. For more on managing asynchronous functions, see Introduction to active objects.

Related concepts