Symbian OS Communications (779884), страница 11
Текст из файла (страница 11)
The options are:ENormalCancel reads and writes, complete when remote end has confirmedcloseEStopInputStop socket input and complete when output is stopped.EStopOutputStop socket output and complete when input is stopped.EImmediateStop socket input/output and complete (abortive close).EStopInput will complete all outstanding reads with KErrCanceland block further reads, but will allow further writes to the socket.EStopOutput will do the opposite: cancelling writes and allowingreads.
Both these options are only supported if the protocol has theKSIGracefulClose property.OVERVIEW OF ESOCK43Table 3.3 Generic options provided by ESOCKOption nameKSODebugRead/ MeaningWriteR/W Debugging enabled ordisabledValues0 – Disabled1 – EnabledNote that this value doesn’tactually do anything!KSORecvBufR/W The receive buffer sizeused in ESOCKKSocketBufSizeUndefined – sets to thedefault size1 to KMaxTUint: explicitbuffer sizeParameter passed as aTPckgBufKSOSendBufR/W The send buffer sizeused in ESOCKKSockBufSizeUndefined – sets to the defaultsize1 to KMaxTUint: explicitbuffer sizeParameter packaged as aTPckgBufKSONonBlockingIOKSOBlockingIOR/W Socket nonblockingmodeTo set: no value neededR/W Socket blocking modeTo set: no value neededTo get: 0 – disabled,1 – enabledTo get: 0 – disabled,1 – enabledKSOSelectPollRReturns a bitmap of flags KSockSelectRead – datadescribing the status of available to readthe socket. Value is aTInt containing socketstatus flagsKSockSelectWrite –writing to the socket is notcurrently blocked by flowcontrolKSockSelectExcept –an error has occurredKSockSelectReadContinuation –(continued overleaf )44AN INTRODUCTION TO ESOCK(continued )Option nameRead/ MeaningWriteValuesincludes tail of prior readdatagram as available data(i.e., indicates next readwill be with readcontinuation)KSOReadBytesPendingRNumber of bytesavailable for readingValue as TIntKSOUrgentDataOffsetROffset into the streamTInt – offset in data forfor urgent data (forurgent dataprotocols that support it)KSOSelectLastErrorRLast error on the socketKSOEnableTransferWEnables socket to beA TSecurityPolicytransferred to anotherpackaged as aprocess with givenTSecurityPolicyBufcapabilities.
This optionmust be called from theprocess owning thesocket prior to aRSocket::Transfer() call beingmade by the receivingprocessKSODisableTransferWDisables the ability totransfer the socketError as a TIntNo value requiredAs with the Connect(), if the protocol supports disconnect data(KSIDisconnectData) then the version that supplies and receives thatdata can be used.There is no way to cancel a shutdown once it has started, as the socketmay already be in a half-closed state from which there is no way for theprotocol to recover.Once a socket has been shut down it cannot be used as all operationsother than Close() will return an error code. Don’t forget that you stillneed to call Close() on the RSocket instance to clean up the ESOCKclient–server resources associated with the handle.Process and thread sharing RSocket instances can be shared betweendifferent threads in a single process. Firstly the RSocketServ must beOVERVIEW OF ESOCK45set to shareable, using the RSocketServ::ShareAuto() function.Appropriate care must be taken to ensure that SendRecv operationsare coordinated between the threads, as only one can be outstandingat a time on a socket.
Patterns such as one thread reading and onethread writing are simple solutions. Care is also needed over closingthe socket, as this should only be done once all threads have stoppedusing it.ESOCK sessions cannot be shared between different processes, andtherefore RSocket and the other ESOCK R-classes cannot be shared inthis way.
However, it is possible to transfer a RSocket from one processto another.This is done using the RSocket::Name() and RSocket::Transfer() calls. The name of the socket to transfer is sent to the process that will receive the socket, and then the receiving process callsRSocket::Transfer() passing the RSocketServ instance to useand the name of the socket.RSocketServ ss;TInt err=ss.Connect();// check err!// name is in sockName variable// must have been passed via other IPC mechanismRSocket sock;err=sock.Transfer(ss, sockName);To be eligible for transfer, the source process must first set the socketas transferable, using a SetOpt()._LIT_SECURITY_POLICY_Cn(KProcPolicy, cap1,cap2,...capn);ret = destsock.SetOpt(KSOEnableTransfer, KSOLSocket,KProcPolicy().Package());// check error!Where cap1, cap2.
. . are the capabilities that the destination processmust have to effect the transfer. By using _LIT_SECURITY_POLICY_Snor a _LIT_SECURITY_POLICY_Vn the transfer can also use a SecureID or Vendor ID to ensure the recipient is a specific process, or a specificvendor’s process.Closing Closing down a socket is performed using the Close() methodcommon to R-classes:void Close();There is a terminology issue here: Close() refers to closing theSymbian OS client–server connection (from your program to ESOCK)46AN INTRODUCTION TO ESOCKrather than closing the connection to the remote peer, which is accomplished using Shutdown() (see above). However, as a side effect ofclosing the RSocket session handle, ESOCK and the protocol modulewill terminate the link to the peer. If the protocol supports graceful closethen this behaves the same as performing a Shutdown(ENormal),otherwise it’s the same as calling Shutdown(EImmediate).There can be problems with graceful close of a socket when callingClose() without calling Shutdown() first.
The problem occurs if moredata is received after the application has called Close(). When thishappens, the graceful close turns into an immediate close. This doesn’tcause problems for your application, but you may see some non-gracefulbehavior on the wire, e.g., when using TCP, RST being sent. If you wantto avoid this behavior, ensure you always use Shutdown() first.3.1.5 Connection ManagementOne of the challenges of communications programming on smartphonesis dealing with the multitude of connectivity options available.
To addressthis complexity Symbian introduced the connection management APIsin v7.0s. As of v9.2, these APIs are largely used to manage IP networkconnections, and so more details are found in Chapter 6.In addition to binding sockets to bearers, the connection managementAPIs provide mechanisms for enumerating, starting, stopping and monitoring connections, although again these are currently limited to IP-basedconnections.RConnectionThe core connection management API is provided by the RConnectionclass found in <es_sock.h>. The class provides two closely relatedservices: the starting/stopping of connections and the monitoring ofconnections.We’ll look at the starting and stopping functionality first:TInt Open(RSocketServ& aSocketServer,TUint aConnectionType = KConnectionTypeDefault);TInt Open(RSocketServ& aSocketServer, TName& aName);void Close();voidvoidTIntTIntTIntTIntTIntTIntStart(TRequestStatus& aStatus);Start(TConnPref& aPref, TRequestStatus& aStatus);Start();Start(TConnPref& aPref);Stop();Stop(TConnStopType aStopType);Stop(TSubConnectionUniqueId aSubConnectionUniqueId);Stop(TSubConnectionUniqueId aSubConnectionUniqueId,TConnStopType aStopType);OVERVIEW OF ESOCK47RConnection objects exist in three states: without a connectionto ESOCK (as is common for most server handles); as an unassociatedconnection and as an associated connection.
The object starts withouta connection to ESOCK, in a similar way to RSocket, and must beconnected using one of the Open() calls. Once the client/server channelto ESOCK is established, then the RConnection object can be associatedwith a specific underlying bearer. Multiple RConnection objects canbe associated with a single bearer connection, which allows multipleprocesses to monitor and control the bearers.To start a bearer, one of the Start() methods is called. The simplest isStart() or Start(TRequestStatus&). Both start the default beareras configured on the device, the difference being the first is synchronousand the latter asynchronous. This may or may not result in the user beingprompted, depending on how the device is configured.
If you want morecontrol over the bearer, use the overloads of Start() which take aTConnPref to allow specific bearers to be selected. TConnPref isa base class – you’ll always need to use one of the derived classes toactually specify what connection you want to open. There’s more detailson this in Chapter 6.Once the connection has been started, you should not attempt toStop() it – despite it being the obvious operation to perform.
Stop()really does mean stop, i.e., terminate the connection. Close() is thecorrect operation to perform on a connection when you’ve finished withit. In the case of IP connections, this will then shut down the networkinterface after an idle period defined in CommsDat.Since a bearer can take a while to initialize and connect, it’s possible toretrieve notifications of the progress, for example to draw a progress bar onthe screen. It is also possible to monitor the connection during its lifetimeto watch for state changes. You may, for example, want to know if theconnection goes down. Monitoring progress is one possible way to do that.Errors from socket operations are another.
Since, for IP at least, errors arereported first via progress notifications, you may find this a better method.The following methods are used to gather progress information:void ProgressNotification(TNifProgressBuf& aProgress,TRequestStatus& aStatus,TUint aSelectedProgress = KConnProgressDefault);void ProgressNotification(TSubConnectionUniqueId aSubConnectionUniqueId,TNifProgressBuf& aProgress, TRequestStatus& aStatus,TUint aSelectedProgress = KConnProgressDefault);void CancelProgressNotification();void CancelProgressNotification(TSubConnectionUniqueIdaSubConnectionUniqueId);TInt Progress(TNifProgress& aProgress);TInt Progress(TSubConnectionUniqueId aSubConnectionUniqueId,TNifProgress& aProgress);TInt LastProgressError(TNifProgress& aProgress);48AN INTRODUCTION TO ESOCKThe remaining methods of RConnection can be used to inspect thestate of a bearer.
The bearer doesn’t have to have been started by yourprogram – it’s possible to enumerate the active bearers and connect toone of these. This is done using:TInt EnumerateConnections(TUint& aCount);TInt GetConnectionInfo(TUint aIndex, TDes8& aConnectionInfo);TInt Attach(const TDesC8& aConnectionInfo, TConnAttachType aAttachType);EnumerateConnections() returns the number of active connections, and GetConnectionInfo() can then retrieve informationabout a specific connection.
Don’t worry about the number of activeconnections changing between EnumerateConnections() and GetConnectionInfo() – the server caches the information at the pointwhen EnumerateConnections() is called, so that even if the connection is stopped it’s still possible to retrieve the information. This doesmean that there’s no guarantee that a connection is still active whenyou get the information, but of course the bearer could be stopped byanother process at any point anyway.