|
1 <?xml version="1.0" encoding="utf-8"?> |
|
2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. --> |
|
3 <!-- This component and the accompanying materials are made available under the terms of the License |
|
4 "Eclipse Public License v1.0" which accompanies this distribution, |
|
5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". --> |
|
6 <!-- Initial Contributors: |
|
7 Nokia Corporation - initial contribution. |
|
8 Contributors: |
|
9 --> |
|
10 <!DOCTYPE reference |
|
11 PUBLIC "-//OASIS//DTD DITA Reference//EN" "reference.dtd"> |
|
12 <reference id="GUID-C1612638-4C5A-5C37-AF1A-16F9EBEF09FD" xml:lang="en"><title>transient: |
|
13 transient server example</title><shortdesc>This example demonstrates the use of transient servers that are |
|
14 started on demand when a client needs to use the server, and exit after the |
|
15 last client has disconnected, sometimes after a short delay. It demonstrates |
|
16 how to handle startup and shutdown situations correctly. </shortdesc><prolog><metadata><keywords/></metadata></prolog><refbody> |
|
17 <section id="GUID-BF4C4CB4-D495-49D6-8035-F8BA724851B7"><title>Class summary</title><ul> |
|
18 <li><p><xref href="GUID-6D8A458C-9A39-3000-A3BC-060A2A3663E6.dita"><apiname>RSessionBase</apiname></xref> - Client-side handle to a session with |
|
19 a server.</p></li> |
|
20 <li><p><xref href="GUID-5733DF34-5B54-3044-BBED-3BFECB7ACE7A.dita"><apiname>CTimer</apiname></xref> - Base class for a timer active object.</p></li> |
|
21 <li><p><xref href="GUID-8E316AC4-4676-301A-9A23-659E83AA1D1C.dita"><apiname>CServer2</apiname></xref> - Abstract base class for servers (version |
|
22 2).</p></li> |
|
23 <li><p><xref href="GUID-D5A30C75-E22C-34E8-913B-7D2CA6AD5C51.dita"><apiname>CSession2</apiname></xref> - Represents a session (version 2) for |
|
24 a client thread on the server-side.</p></li> |
|
25 </ul></section> |
|
26 <section id="GUID-E688F8C0-0A4A-4D25-B7B4-779CB6A08157"><title>Download</title> <p>Click on the following link to download |
|
27 the example: <xref href="guid-6013a680-57f9-415b-8851-c4fa63356636/zips/guid-cbf7e18e-3788-4ec1-a225-268ce1a22c51.zip" scope="external">transient.zip</xref></p><p>click: <xref href="guid-6013a680-57f9-415b-8851-c4fa63356636/guid-cbf7e18e-3788-4ec1-a225-268ce1a22c51.html" scope="peer">browse</xref> to view the example code.</p> </section> |
|
28 <section id="GUID-87B18963-ACE8-464B-9863-A37ADA57379C"><title>Background</title> <p>The client-server framework is an important |
|
29 part of Symbian platform. There is a level of complexity in implementing a |
|
30 server for an application, but this example provides client interface code |
|
31 and server code that can be re-used in your own implementations. </p> <p>Symbian |
|
32 platform servers are of three basic types: </p> <ul> |
|
33 <li id="GUID-6D0F8C69-CFEA-5BB1-A0CB-C4D178DFAE25"><p> <b>Transient servers:</b> these |
|
34 are started on demand when a client needs the server, and exit after the last |
|
35 client has disconnected - sometimes after a short delay, for example, the |
|
36 socket server. </p> </li> |
|
37 <li id="GUID-5B824584-C8E6-57F7-A83C-564DA256F622"><p> <b>System servers:</b> these |
|
38 are started as part of the system boot process, for example, the kernel, the |
|
39 file server, the window server etc. </p> </li> |
|
40 <li id="GUID-9BE0FD09-B112-5AF6-A5D1-FBDD6A4EC00B"><p> <b>Local servers:</b> these |
|
41 are "local" to a process to provide multi-threaded access to thread-specific |
|
42 resources, for example, the posix server (in the C Standard Library). </p> </li> |
|
43 </ul> </section> |
|
44 <section id="GUID-EEA0A38B-F8A6-4308-A50D-B3E74B12420A"><title>Description</title> <p>The transient server supplied here |
|
45 runs in a thread in its own process. This gives the server independence from |
|
46 its clients. This is important because if the client were to create the server |
|
47 as a separate thread within its own process, then the server would exit, i.e. |
|
48 terminate, if its owning process terminated. This would be true even if clients |
|
49 in other processes were still connected to it. </p> <p>Equally as important: </p> <ul> |
|
50 <li id="GUID-432FCF7B-2393-5E59-BDE5-0A5B4BAFD155"><p>a client does not explicitly |
|
51 need to start the server prior to connecting; this is done by the client interface. </p> </li> |
|
52 <li id="GUID-D89C8F48-2CA2-5769-8DB9-42FD8FFA5879"><p>the server terminates |
|
53 when not in use shortly after the last client disconnects. </p> </li> |
|
54 <li id="GUID-968AB243-908B-5709-BB82-4213860CBC8A"><p>the code handles concurrency |
|
55 issues, the most common of which is handling the case where the server is |
|
56 closing down or exiting at the same time that another client is trying to |
|
57 connect. </p> </li> |
|
58 </ul> <p>The example consists of four main parts: </p> <ul> |
|
59 <li id="GUID-BC6A15E0-07CB-562C-99E8-0AAF39B0ED26"><p>Client interface: this |
|
60 is a DLL (<filepath>t-client.dll</filepath>) that is used by clients. </p> <p>The |
|
61 client interface effectively forms the gateway to the server. All requests |
|
62 to the server, including requests to connect to it are routed through this. </p> <p>The |
|
63 client interface defines just one class: <codeph>RMySession</codeph>, derived |
|
64 from <xref href="GUID-6D8A458C-9A39-3000-A3BC-060A2A3663E6.dita"><apiname>RSessionBase</apiname></xref>. An <codeph>RSessionBase</codeph> (derived) |
|
65 object represents the client side session and forms a channel of communication |
|
66 between the client and the server. Requests to the server, and information |
|
67 received from the server are channelled through this object. Note that the |
|
68 client side session object is mirrored by a server side session object; an |
|
69 instance of a class derived from <xref href="GUID-D5A30C75-E22C-34E8-913B-7D2CA6AD5C51.dita"><apiname>CSession2</apiname></xref>, which in this |
|
70 server is called <codeph>CMySession</codeph>. </p> <p>The client calls <codeph>Connect()</codeph> to |
|
71 set up a connection to the server. This function attempts to start the server |
|
72 if necessary and then issues a request to create a session with the server. |
|
73 If the server fails to start, or a session cannot be created then this is |
|
74 reported back.Simultaneous launching of two server processes is also detected, |
|
75 with the second attempt failing with <xref href="GUID-D1D25122-F2B8-3C78-8599-84905BFD47B8.dita"><apiname>KErrAlreadyExists</apiname></xref>. |
|
76 On successful completion the connection is established, and a session is created |
|
77 with the server. </p> <p>The client uses the <codeph>Send()</codeph> method |
|
78 to send messages to the server and the <codeph>Receive()</codeph> method to |
|
79 request information from the server. <codeph>Send()</codeph> is implemented |
|
80 by calling down to the synchronous variant of <xref href="GUID-6D8A458C-9A39-3000-A3BC-060A2A3663E6.dita#GUID-6D8A458C-9A39-3000-A3BC-060A2A3663E6/GUID-479FE087-DD9F-31D7-98F7-9F96535F0584"><apiname>RSessionBase::SendReceive()</apiname></xref> in |
|
81 the base class. Synchronous means that it does not return until the server |
|
82 has dealt with the request. </p> <p> <codeph>Send()</codeph> passes an operation |
|
83 code (or function number) identifying the request and a descriptor containing |
|
84 information to the server. The descriptor is wrapped into a <xref href="GUID-4AD02F14-1142-372F-9D11-224595932034.dita"><apiname>TIpcArgs</apiname></xref> object. |
|
85 In practice, your client interface would probably be richer, having variants |
|
86 of the <codeph>Send()</codeph> function that take more than one parameter. |
|
87 You might also choose to have asynchronous variants of <codeph>Send()</codeph>; |
|
88 your client code (not the client interface) would then need to use active |
|
89 objects to deal with this. </p> <p> <codeph>Receive()</codeph> is implemented |
|
90 by calling down to the asynchronous variant of <xref href="GUID-6D8A458C-9A39-3000-A3BC-060A2A3663E6.dita#GUID-6D8A458C-9A39-3000-A3BC-060A2A3663E6/GUID-479FE087-DD9F-31D7-98F7-9F96535F0584"><apiname>RSessionBase::SendReceive()</apiname></xref> in |
|
91 the base class. Asynchronous means that the call returns immediately, but |
|
92 the request itself may not complete until some time later. </p> <p> <codeph>Receive()</codeph> passes |
|
93 an operation code (or function number) identifying the request, a descriptor |
|
94 into which the server will place the information, and a <xref href="GUID-E0B34F3E-D4C4-3232-B8B1-7DB35B454646.dita"><apiname>TRequestStatus</apiname></xref> object, |
|
95 which the server will use to report how the request completes. The descriptor |
|
96 is wrapped into a <xref href="GUID-4AD02F14-1142-372F-9D11-224595932034.dita"><apiname>TIpcArgs</apiname></xref> object. Again, you might want |
|
97 a richer client interface; perhaps different function names to represent different |
|
98 request types. </p> <p> <codeph>CancelReceive()</codeph> allows the client |
|
99 to cancel a pending <codeph>Receive()</codeph> request. It is usual to provide |
|
100 some mechanism to cancel asynchronous requests. This is implemented by calling |
|
101 down into the asynchronous variant of <xref href="GUID-6D8A458C-9A39-3000-A3BC-060A2A3663E6.dita#GUID-6D8A458C-9A39-3000-A3BC-060A2A3663E6/GUID-479FE087-DD9F-31D7-98F7-9F96535F0584"><apiname>RSessionBase::SendReceive()</apiname></xref> in |
|
102 the base class. Note: the <codeph>Receive()</codeph> method simply passes |
|
103 an operation code (or function number) and no data. </p> <p>The operation |
|
104 codes (or function numbers) are defined by an enum in the header file <filepath>clientserver.h</filepath>. |
|
105 This file is included in both the client interface code and server code as |
|
106 both need access to these common symbols. </p> </li> |
|
107 <li id="GUID-A76A5A09-CB86-5D58-8771-3DE4131E51B9"><p>Server: this is an EXE |
|
108 (<filepath>t-server.exe</filepath>) that runs in its own process, and E32Main() |
|
109 is the entry point. After setting up heap checking (in debug builds only) |
|
110 the implementation creates a cleanup stack and then executes the main body |
|
111 of the code inside a trap harness. </p> <p>The server code implements several |
|
112 classes: </p> <p> <codeph>CMyServer</codeph>: this class derives from the |
|
113 class <xref href="GUID-8E316AC4-4676-301A-9A23-659E83AA1D1C.dita"><apiname>CServer2</apiname></xref>. The main role of this class is to handle |
|
114 messages sent by client threads; this includes requests from clients for connection |
|
115 to the server. The connection is established by starting a session with the |
|
116 server. The session is represented by a session object, in this case the <xref href="GUID-8B50E9C7-CA33-3E11-A881-16E230A082CB.dita"><apiname>CMySession</apiname></xref> object. </p> <p>Once |
|
117 the <codeph>CMyServer</codeph> object has been created, the active scheduler |
|
118 can be started by the call to <xref href="GUID-B4C76104-EA1B-3FC3-A31E-86A976598171.dita#GUID-B4C76104-EA1B-3FC3-A31E-86A976598171/GUID-3281C85C-1A45-3049-B711-64CA8BFBC452"><apiname>CActiveScheduler::Start()</apiname></xref>. |
|
119 This call will not return until the active scheduler is stopped by the <codeph>CShutdown</codeph> timer, |
|
120 which is primed after the last client has disconnected. In simple terms, the |
|
121 active scheduler is a wait loop. It sits inactive until it receives a message |
|
122 from (potential) clients (or until the timer completes and stops the active |
|
123 scheduler). Messages that represent requests for connection result in the |
|
124 creation of a session. Other messages are passed to the relevant <codeph>CMySession</codeph> active |
|
125 object. </p> <p> <codeph> CMySession</codeph>: one of these objects is created |
|
126 for each session, i.e. as a result of a request by a client for connection |
|
127 to the server. Once sessions have been created, requests received by <codeph>CMyServer</codeph> are |
|
128 then forwarded to the corresponding session, and specifically to the virtual |
|
129 function <codeph>ServiceL()</codeph>, which handles <codeph>Send()</codeph>, <codeph>Receive()</codeph> and <codeph>CancelReceive()</codeph> requests. </p> <p> <codeph>CShutdown</codeph>: this class represents a timer that is started |
|
130 before the first client has connected, and after the last client has disconnected. |
|
131 The timer is stopped once the server has at least one client attached to it. |
|
132 If the server has no clients, then there is 2 second interval before the server |
|
133 terminates. This is implemented as an active object. </p> </li> |
|
134 <li id="GUID-07B2ACEC-C457-547D-B1FE-78FCF980AEEF"><p>Test code:this corresponds |
|
135 to the client, and uses the client interface to communicate with the server |
|
136 - application developers should make use of the principles applied here and |
|
137 include them into their own client code. </p> </li> |
|
138 <li id="GUID-91B89143-B380-524D-89CF-918FAE5CE055"><p>bld.inf: which is a |
|
139 component description file. </p> </li> |
|
140 </ul><p><b>Related APIs</b></p><ul> |
|
141 <li><p><xref href="GUID-B4C76104-EA1B-3FC3-A31E-86A976598171.dita#GUID-B4C76104-EA1B-3FC3-A31E-86A976598171/GUID-3281C85C-1A45-3049-B711-64CA8BFBC452"><apiname>CActiveScheduler::Start()</apiname></xref></p></li> |
|
142 <li><p><xref href="GUID-8B50E9C7-CA33-3E11-A881-16E230A082CB.dita"><apiname>CMySession</apiname></xref></p></li> |
|
143 <li><p><xref href="GUID-8E316AC4-4676-301A-9A23-659E83AA1D1C.dita"><apiname>CServer2</apiname></xref> - Abstract base class for servers (version |
|
144 2).</p></li> |
|
145 <li><p><xref href="GUID-D5A30C75-E22C-34E8-913B-7D2CA6AD5C51.dita"><apiname>CSession2</apiname></xref> - Represents a session (version 2) for |
|
146 a client thread on the server-side.</p></li> |
|
147 <li><p><xref href="GUID-D1D25122-F2B8-3C78-8599-84905BFD47B8.dita"><apiname>KErrAlreadyExists</apiname></xref> - System wide error code -11 : |
|
148 an object already exists.</p></li> |
|
149 <li><p><xref href="GUID-6D8A458C-9A39-3000-A3BC-060A2A3663E6.dita"><apiname>RSessionBase</apiname></xref> - Client-side handle to a session with |
|
150 a server.</p></li> |
|
151 <li><p><xref href="GUID-6D8A458C-9A39-3000-A3BC-060A2A3663E6.dita#GUID-6D8A458C-9A39-3000-A3BC-060A2A3663E6/GUID-479FE087-DD9F-31D7-98F7-9F96535F0584"><apiname>RSessionBase::SendReceive()</apiname></xref></p></li> |
|
152 <li><p><xref href="GUID-4AD02F14-1142-372F-9D11-224595932034.dita"><apiname>TIpcArgs</apiname></xref> - A Version 2 client/server class that |
|
153 clients use to package the arguments to be sent to a server.</p></li> |
|
154 <li><p><xref href="GUID-E0B34F3E-D4C4-3232-B8B1-7DB35B454646.dita"><apiname>TRequestStatus</apiname></xref> - Indicates the completion status |
|
155 of a request made to a service provider.</p></li> |
|
156 </ul> </section> |
|
157 <section id="GUID-86D3479E-216B-4D5D-AF57-C4C9963CD9F0"><title>Building and configuring</title> <p>To build the example: </p> <ul> |
|
158 <li id="GUID-FDC690A6-D68B-58E5-A10D-89220DB9B89E"><p>You can build the example |
|
159 from your IDE or the command line. </p> <p>If you use an IDE, import the <filepath>bld.inf</filepath> file |
|
160 of the example into your IDE, and use the build command of the IDE. </p> <p>If |
|
161 you use the command line, open a command prompt, and set the current directory |
|
162 to the source code directory of the example. You can then build the example |
|
163 with the SBSv1 build tools with the following commands: </p> <p><userinput>bldmake |
|
164 bldfiles</userinput> </p> <p><userinput>abld build</userinput> </p> <p><xref href="GUID-793A5EF9-CC16-5EEB-9011-6431EA76EB15.dita">How to use bldmake</xref> and <xref href="GUID-B6B54E07-3B34-5D5C-8815-93383FA8FB4B.dita">How to use abld</xref> describe |
|
165 how to use the SBSv1 build tools. </p> </li> |
|
166 <li id="GUID-DD18F4AF-6AB1-5E0F-95C3-9EB899BA99C9"><p>For the emulator, the |
|
167 example builds the following executables : </p> <p> <filepath>t-client.dll</filepath> </p> <p> <filepath>t-server.exe</filepath> </p> <p> <filepath>t-test.exe</filepath> (test executable) </p> <p> <filepath>t-testc.dll</filepath> (test |
|
168 client) </p> <p>in the <filepath>epoc32\release\winscw\<udeb or urel>\</filepath> folder. </p> </li> |
|
169 </ul> </section> |
|
170 </refbody><related-links> |
|
171 <link href="GUID-4BFEDD79-9502-526A-BA7B-97550A6F0601.dita"><linktext>Platform |
|
172 security</linktext></link> |
|
173 <link href="GUID-B21141D4-3BFE-59C9-8D5F-147A93BE1C95.dita"><linktext>Build tools |
|
174 guide</linktext></link> |
|
175 <link href="GUID-594488FF-02C9-5066-85DB-5F88A754AE18.dita"><linktext>How |
|
176 to build DLLs</linktext></link> |
|
177 <link href="GUID-BBBB5000-90A2-503A-9521-2FC6DEC69DC8.dita"><linktext>MMP file |
|
178 syntax</linktext></link> |
|
179 </related-links></reference> |