How to create a server from scratch

 

 

 

This code shows how to create a server from scratch. It shows how to implement the server class, that represents the server itself, and the session, that is created for each communication channel opened from client to server. 

ID   Creation date March 16, 2008 

Platform S60 3rd Edition S60 3rd Edition, FP1 Tested on devices

Category Symbian C++ Subcategory

 

server, implementation 

 

 

Contents

[hide]

  1 Overview 

  2 Types 

  3 Server Implementation 

  4 Session implementation 

  5 MMP file (optional) 

  6 Conclusions 

  7 Related links 

 

[edit] Overview 

This example shows how to implement a server from scratch step-by-step. It assumed previous knowledge related to the client/server framework (ex. Client-Server Framework). 

This example deals with the synchronous requests only. Asynchronous request can be found in Implementing asynchronous requests. 

The client counterpart implementation of the server can be viewed here Client side implementation of a server. 

[edit] Types 

1.System Server: Starts with the mobile phone, essential for the OS (e.g. File Server, Window Server). Unexpected termination usually forces phone reboot. 

2.Application / Transient Server: Started on request of an application, closed when last client disconnects.If a second client starts a new server, no error is produced, existing server instance is used. 

3.Other Servers: Started and closed with an individual application. If used by multiple applications: each app. has its own private instance; e.g. POSIX server. 

[edit] Server Implementation 

A server implementation is based mainly on two objects: 

1. The server object, of CServer2 type. 

2. The sessions objects, of CSession2 type. 

Servers usually run in their own process, but at least in a separate thread. Because of this, a server has to install the clean-up stack and the Active Scheduler for the thread it is going to run in. So the first thing to do is to install the clean-up stack and then the active scheduler. The following code shows how to do this. 

First step: Install the cleanup stack 

CTrapCleanup* cleanupStack = CTrapCleanup::New();

 if ( !( cleanupStack ) )

    {

     // cannot go on. Need to panic the server. We cannot live without cleanup stack :)

    }

 // initialize and starts active scheduler

Second step: Install and start active scheduler 

// Construct active scheduler

 CActiveScheduler* activeScheduler = new ( ELeave ) CActiveScheduler;

 //We can use the stack here. It is alrady installed!

 CleanupStack::PushL( activeScheduler );

 

 // Install active scheduler

 CActiveScheduler::Install( activeScheduler );

 

 //Instantiate server object here!

 

 //Starts the scheduler. Thread remains in this loop until the process is terminated.

 CActiveScheduler::Start();

Third step: Specify and create the server object Before starting the scheduler it is necessary to create the server object. The class that specifies the server object is derived from the CServer2 class (from Symbian OS v9.x onwards). The main goals of the server are to keep track of the number of sessions that are opened to it and to create new session objects for each opened session with the clients. Due to this, the main functions of the server class are IncrementSessions, DecrementSessions and NewSessionL. The following code shows an implementation of the server class. It was obtained from S60Ex folder of SDK named ClientServerSync. 

The header file. 

/**

* CTimeServer.

*  An instance of class CTimeServer is the main server class

*  for the ClientServerSync example application

*  Just the main functions are showed here!

*/

class CTimeServer : public CServer2

    {

    public: // New functions

 

        /**

        * ThreadFunction.

        * Main function for the server thread.

        * @param aNone Not used.

        * @return Error code.

        */

        static TInt ThreadFunction( TAny* aNone );

 

        /**

        * IncrementSessions.

        * Increments the count of the active sessions for this server.

        */

        void IncrementSessions();

 

        /**

        * DecrementSessions.

        * Decrements the count of the active sessions for this server.

        * If no more sessions are in use the server terminates.

        */

        void DecrementSessions();

 

    private: // New methods

 

        /**

        * ThreadFunctionL.

        * Second stage startup for the server thread.

        */

        static void ThreadFunctionL();

 

    private: // Functions from base classes

 

        /**

        * From CServer, NewSessionL.

        * Create a time server session.

        * @param aVersion The client version.

        * @param aMessage Message from client.

        * @return Pointer to new session.

        */

        CSession2* NewSessionL( const TVersion& aVersion, 

                                const RMessage2& aMessage ) const;

 

    };

The source code. 

// -----------------------------------------------------------------------------

// CTimeServer::NewSessionL()

// Creates a time server session.

// Just the main functions are showed here!

// -----------------------------------------------------------------------------

//

CSession2* CTimeServer::NewSessionL( const TVersion& aVersion, 

                                     const RMessage2& /*aMessage*/ ) const

    {

    // Check we are the right version

    if ( !User::QueryVersionSupported( TVersion( KTimeServMajorVersionNumber,

                                                 KTimeServMinorVersionNumber,

                                                 KTimeServBuildVersionNumber ),

                                       aVersion ) )

        {

        User::Leave( KErrNotSupported );

        }

 

    // Make new session        

    return CTimeServerSession::NewL( *const_cast<CTimeServer*> ( this ) );

    }

 

// -----------------------------------------------------------------------------

// CTimeServer::IncrementSessions()

// Increments the count of the active sessions for this server.

// -----------------------------------------------------------------------------

//

void CTimeServer::IncrementSessions()

    {

    iSessionCount++;

    }

 

// -----------------------------------------------------------------------------

// CTimeServer::DecrementSessions()

// Decrements the count of the active sessions for this server.

// -----------------------------------------------------------------------------

//

void CTimeServer::DecrementSessions()

    {

    iSessionCount--;

    if ( iSessionCount <= 0 )

        {

        CActiveScheduler::Stop();

        }

    }

 

// -----------------------------------------------------------------------------

// CTimeServer::ThreadFunctionL()

// Second stage startup for the server thread.

// Creates and starts the active scheduler

// -----------------------------------------------------------------------------

//

void CTimeServer::ThreadFunctionL()

    {

    // Construct active scheduler

    CActiveScheduler* activeScheduler = new ( ELeave ) CActiveScheduler;

    CleanupStack::PushL( activeScheduler );

 

    // Install active scheduler

    // We don't need to check whether an active scheduler is already installed

    // as this is a new thread, so there won't be one

    CActiveScheduler::Install( activeScheduler );

 

    // Construct our server, leave it on clean-up stack

    CTimeServer::NewLC();    // Anonymous

 

    RSemaphore semaphore;

    User::LeaveIfError( semaphore.OpenGlobal( KTimeServerSemaphoreName ) );

 

    // Semaphore opened ok

    semaphore.Signal();

    semaphore.Close();

 

    // Start handling requests

    CActiveScheduler::Start();

 

    CleanupStack::PopAndDestroy( 2, activeScheduler ); //Anonymous CTimeServer

    }

 

// -----------------------------------------------------------------------------

// CTimeServer::ThreadFunction()

// Main function for the server thread.

// Creates the cleanup stack

// -----------------------------------------------------------------------------

//

TInt CTimeServer::ThreadFunction( TAny* /*aNone*/ )

    {

    CTrapCleanup* cleanupStack = CTrapCleanup::New();

    if ( !( cleanupStack ) )

        {

        PanicServer( ECreateTrapCleanup );

        }

 

    TRAPD( err, ThreadFunctionL() );

    if ( err != KErrNone )

        {

        PanicServer( ESrvCreateServer );

        }

 

    delete cleanupStack;

    cleanupStack = NULL;

 

    return KErrNone;

    }

 

// -----------------------------------------------------------------------------

// E32Main()

// Provides the API for the operating system to start the executable.

// Returns the address of the function to be called.

// -----------------------------------------------------------------------------

//

TInt E32Main()

    {

    return CTimeServer::ThreadFunction( NULL );

    }

[edit] Session implementation

Fourth step: Specifies the session class Every time a client connects to a server a session object is created in each side. In the server side, this objects manages the connection among server and client. It is responsible for receiving and answering client's requests. This object is derived from the class CSession2 and needs to implement the method ServiceL from which the client's requests arrives. This is the main function of this object. The following code shows an example of session class implementation. Observe that the creation and deletion of each session object implies in a call to IncrementSessions and DecrementSessions of the server object. 

The header file. 

/**

* CTimeServerSession.

*  An instance of class CTimeServerSession is created for each client.

*  Just the main functions are showed here!

*/

class CTimeServerSession : public CSession2

    {

    public: // Constructors and destructors

        /**

        * NewL.

        * Two-phased constructor.

        * @param aServer The server.

        * @return Pointer to created CTimeServerSession object.

        */

        static CTimeServerSession* NewL( CTimeServer& aServer );

 

        /**

        * NewLC.

        * Two-phased constructor.

        * @param aServer The server.

        * @return Pointer to created CTimeServerSession object.

        */

        static CTimeServerSession* NewLC( CTimeServer& aServer );

 

        /**

        * ~CTimeServerSession.

        * Destructor.

        */

        virtual ~CTimeServerSession();

 

    public: // Functions from base classes

 

        /**

        * From CSession, ServiceL.

        * Service request from client.

        * @param aMessage Message from client

        *                 (containing requested operation and any data).

        */

        void ServiceL( const RMessage2& aMessage );

    };

The source code. 

// -----------------------------------------------------------------------------

// CTimeServerSession::ConstructL()

// Symbian 2nd phase constructor can leave.

// Increments the server sessions.

// Just the main functions are showed here!

// -----------------------------------------------------------------------------

//

void CTimeServerSession::ConstructL()

    {

    iServer.IncrementSessions();

    }

 

// -----------------------------------------------------------------------------

// CTimeServerSession::~CTimeServerSession()

// Destructor.

// Decrement the number of server sessions.

// -----------------------------------------------------------------------------

//

CTimeServerSession::~CTimeServerSession()

    {

    iServer.DecrementSessions();

    }

 

// -----------------------------------------------------------------------------

// CTimeServerSession::ServiceL()

// Service request from client.

// -----------------------------------------------------------------------------

//

void CTimeServerSession::ServiceL( const RMessage2& aMessage )

    {

    switch ( aMessage.Function() )

        {

        case ETimeServRequestTime :

            RequestTimeL( aMessage );

            break;

 

        default:

            PanicClient( aMessage, EBadRequest );

            break;

        }

    aMessage.Complete( KErrNone );

    }

 

// -----------------------------------------------------------------------------

// CTimeServerSession::RequestTimeL()

// Called as a result of the client requesting the time.

// -----------------------------------------------------------------------------

//

 

void CTimeServerSession::RequestTimeL( const RMessage2& aMessage )

    {    

    TTime time;

    time.HomeTime();

 

    TPtr8 ptr( reinterpret_cast<TUint8*>( &time ), sizeof( time ),

               sizeof( time ) );

 

    // Write time data to the descriptor which is the first message argument

    aMessage.WriteL( 0, ptr, 0 );    

    }

[edit] MMP file (optional)

The following capabilities are required: 

CAPABILITY none 

[edit] Conclusions

This code shows step-by-step the implementation of a server. This example shows the server-side implementation. This implementation would generate an EXE binary (the server side). For the clients to use this server a client side implementation is also necessary. Usually this implementation come as a DLL. An example of how to implement this DLL can be found here (link to client side implementation). 

 

[edit] Related links 

  Client side implementation of a server 

  Client-Server Framework 

  Inter Process Communication in Symbian 

 

内容概要:本文详细介绍了太阳能电池片在线颜色分选系统的图像预处理方法。针对采集的原始图像中存在的传送带背景和随机倾斜等问题,提出了完整的预处理流程。主要包括:倾斜校正(通过边缘检测和霍夫变换)、去除栅格干扰(频域滤波和形态学操作),以及对多种边缘检测算子(如Roberts、Sobel、Prewitt、Canny和LOG)的比较与分析。此外,还探讨了不同直线检测方法(如Radon变换、Hough变换及其改进版本)的应用,并优化了整个预处理流程,确保后续的颜色特征提取和分类准确性。 适用人群:从事计算机视觉、图像处理领域的研究人员和技术人员,特别是专注于工业自动化检测设备开发的工程师。 使用场景及目标:①实现太阳能电池片图像的倾斜校正,确保图像水平放置;②有效去除电池片表面栅线对颜色分析的影响;③为后续的颜色特征提取和分类提供高质量的输入数据;④比较不同边缘检测算子的效果,选择最适合特定任务的算子;⑤评估各种直线检测方法的性能,选择最优方案应用于实际生产环境中。 其他说明:文中不仅提供了详细的理论解释,还给出了具体的Python代码实现,帮助读者更好地理解和实践相关技术。同时,针对实际应用中的常见问题,如参数调优、光照一致性和异常处理等方面也给出了相应的建议。最后,通过一系列实验验证了所提方法的有效性,并提出了一些性能优化的方向。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值