quick_recipes (779892), страница 52
Текст из файла (страница 52)
When an attribute request completes, each single attribute is returned with its attribute ID using AttributeRequestResult(). A schematic example is shown below:void CServiceDiscoverer::AttributeRequestResult(TSdpServRecordHandle /*aHandle*/,TSdpAttributeID /*aAttrID*/,CSdpAttrValue* aAttrValue){// process it here}The ID of the attribute is given in aAttrID, and the attribute value itselfin aAttrValue parameters. You can find the type of the attribute throughaAttrValue->Type() and cast aAttrValue on this basis to thecorrect subclass of CSdpAttrValue; for instance, for ETypeBooleanyou get CSdpAttrValueBoolean.When there are no more attributes to be returned, the AttributeRequestComplete() method is called:void CServiceDiscoverer::AttributeRequestComplete(TSdpServRecordHandle /*aHandle*/,TInt aError){if (aError==KErrNone){// done with attributes for this record, request next// service recordTRAPD(err, iAgent->NextRecordRequestL());if(err != KErrNone){// handle an error here}}else{// error, should terminate discoverer?}}4.9.2 Intermediate Recipes4.9.2.1Use the Sockets APIAmount of time required: 20 minutesLocation of example code: \Connectivity\IRSocketRequired library(s): bluetooth.lib, btmanclient.lib,sdpagent.lib, sdpdatabase.lib, esock.libRequired header file(s):Required platform security capability(s): LocalServicesCONNECTIVITY291Problem: You want to use the Sockets API to transfer data over Bluetoothor IrDA.Solution: The ESOCK framework can be helpful in many programmingtasks which deal with connectivity on Symbian OS – for instance, todiscover devices for a number of communication protocols such as IrDAor Bluetooth.
In this recipe we will use the Sockets API for data transferswith regard to Infrared and Bluetooth. The whole scenario is pretty muchthe same as the one you might follow for regular networking, but with afew additional steps for selected protocols.The first step for both Infrared and Bluetooth transports at client-side isto discover the available devices to communicate with, just as describedin previous recipes in this section. The rest is exactly the same as forregular sockets; that is, you should open the socket, define a remote port,connect the client socket to the remote host or bind the server socketto a local address and listen for an incoming connection.
If you aredeveloping both client and server applications then you do not need toworry about remote port querying because it will be well known for bothparts. In all other cases you will be required to perform service discoveryto detect the remote port number. Thus, on the client side, you mightwrite something like the following snippet:TNameEntry log;TProtocolInfo pInfo;...// log and pInfo variables get their values during device resolution// process, as well as portNoRSocket sender;sender.Open(ss,pInfo.iAddrFamily,pInfo.iSockType,pInfo.iProtocol);log.iAddr.SetPort(portNo);TRequestStatus stat;sender.Connect(log.iAddr,stat);User::WaitForRequest (stat);TBuf<100> b;b.FillZ();sender.Write(b,stat);User::WaitForRequest (stat);sender.Read(b,stat);User::WaitForRequest (stat)At the same time, on the server side you have to code it as:// Open a listener socket for given protocolRSocket listener;sock.Open(ss,pInfo.iAddrFamily,pInfo.iSockType,pInfo.iProtocol);// Set a port number and bind the socket to the local address292SYMBIAN C++ RECIPESTSockAddr a;a.SetPort(portNo);listener.Bind(a);// Start listeninglistener.Listen(1);// Create data socketRSocket acceptor;acceptor.Open(ss); // Create a null socket to hold the connection// Accept the incoming connection when the request arrivesTRequestStatus stat;listener.Accept(acceptor,stat);User::WaitForRequest (stat); // con now holds the connected socket// Read from connected socketTBuf<100> b;b.FillZ();acceptor.Read(b,stat); // Reading from accepted socket.User::WaitForRequest (stat);// Write data backacceptor.Write(b,stat);User::WaitForRequest (stat);Discussion: IrDA sockets usually connect to known ports on the remotedevice.
The SDK documentation contains samples for a simple beamingapplication to illustrate straightforward ways of making IR connections.In more complicated situations your code may employ an IAS query togather all required information about the remote IR device.
You will notdo this often unless you have to interface to devices that require it. Thecode below is just one possible example of an IAS query implementation:void IASQuery(RNetDatabase &aIAS,const TDesC8 &aClassName,const TDesC8 &aAttributeName,TUint aRemDevAddr)//// Synchronous IAS query. RTimer timeout of 5 seconds on the query.//{TBuf<64> res;TIASQuery querybuf(aClassName,aAttributeName,aRemDevAddr);TRequestStatus stat1,stat2;TIASResponse results;aIAS.Query(querybuf,results,stat2);RTimer tim;tim.CreateLocal();tim.After(stat1,5000000L);User::WaitForRequest(stat1,stat2);if (stat1.Int()==KErrNone) // TIMER COMPLETED - IAS QUERY{// REQUEST HAS TIMED OUT.aIAS.Cancel();return;}else if (stat2.Int()==KErrNone) // IAS QUERY COMPLETED OK.{switch(results.Type())CONNECTIVITY293{case EIASDataMissing: // Missingbreak;case EIASDataInteger: // IntegerTInt num;if (results.GetInteger(num)==KErrNone){TinyTPPort=TUint8(num);}else{// Bad type}break;case EIASDataOctetSequence: // Byte sequenceresults.GetOctetSeq(res);DumpBuf(res);break;case EIASDataUserString: // Stringres.Copy(results.GetCharString8());break;default: // Bad typebreak;}tim.Cancel();}else if (stat2.Int()!=KErrNone) // IAS QUERY COMPLETED UNSUCCESSFULLY.{switch (stat2.Int()){case KErrUnknown: // No such attributebreak;case KErrBadName: // No such classbreak;default: // Unknown errorbreak;}tim.Cancel();}else{tim.Cancel(); // Unknown error on IAS query}};What may go wrong when you do this: If the client application usesthe Bluetooth PAN profile for data transfer, the application will needthe NetworkServices platform security capability in addition toLocalServices.2944.9.2.2SYMBIAN C++ RECIPESCreate a Simple OBEX ClientAmount of time required: 20 minutesLocation of example code: \Connectivity\ObexClientAppRequired library(s): irobex.lib, obex.libRequired header file(s): obex.h, btsdp.hRequired platform security capability(s): LocalServicesProblem: You want to create an OBEX client connection over IrDA orBluetooth and send an object.Solution: The CObexClient class handles all that you need to instantiate and set up a simple OBEX client.
It allows you to pass theTObexProtocolInfo-derived parameter to the CObexClient::NewL() method, which describes the transport layer you want to use. Inthis particular case we will use IrDA, so we need to supply TObexIrProtocolInfo as described below:_LIT8(KIrdaClassName, "OBEX");_LIT8(KIrdaTransportAttrName, "IrDA:TinyTP:LsapSel");// Create transport infoTObexIrProtocolInfo transportInfo;//assigning the unique name for the irda transporttransportInfo.iTransport = KObexIrTTPProtocol;//assigning IrDA specific attributestransportInfo.iClassName = KIrdaClassName;transportInfo.iAttributeName = KIrdaTransportAttrName;//create the OBEX clientiClient = CObexClient::NewL(transportInfo);The next step is to establish a connection to the OBEX server, which isas simple as this:_LIT8(KSampleLocalInfo," IrOBEXFile ");TObexConnectInfo localInfo = iClient->LocalInfo();localInfo.iWho = KNullDesC8;iLocalInfo.iWho.Append(KSampleLocalInfo);// Connect to Obex clientiClient->Connect(iStatus);Once the connection to the OBEX server is established, we canuse various OBEX commands.
You may also need to set up OBEXobjects, which can be done in a few different ways. Please refer to thedocumentation for more details. In this simple case we just PUT the fileto the server (please note that the iFileObject member variable is ofCObexFileObject type):CONNECTIVITY295TRAPD (err, iFileObject->InitFromFileL (aFilename));iClient->Put(*iFileObject,iStatus);Finally, the client has to disconnect from the server after all transfersare completed:iClient->Disconnect(iStatus);You can use a Bluetooth connection for OBEX communication prettymuch in the same manner as over IrDA. Again, CObexClient handlesall you need to instantiate and set up a simple OBEX client. The obviousdifference is that you should launch a device and service discovery priorto any connection attempts, and supply appropriate protocol informationto the CObexClient::NewL() method.
For Bluetooth it will be aTObexBluetoothProtocolInfo structure. The sample code belowassumes that we have already performed the device and service discovery,as in a Recipe 4.9.1.4 and have obtained a Bluetooth address for a givenremote device:// Create transport infoTObexBluetoothProtocolInfo transportInfo;// Set Bluetooth addresstransportInfo.iAddr.SetBTAddr(devAddr);// Set the porttransportInfo.iAddr.SetPort(devPort);// Set transport as RFCommtransportInfo.iTransport = KObexRfcommProtocol;//create the OBEX clientiClient = CObexClient::NewL(transportInfo);After the OBEX client is created successfully, the rest is just the sameas with the IrDA client described earlier in this recipe.Discussion: IrDA OBEX servers use IAS to publish their service information. To access the default OBEX server, the IAS class value should beOBEX and the IAS attribute name IrDA:TinyTP:LsapSel. If there areother OBEX services available, they have to be registered and the standardIAS discovery procedure should be used by clients to detect them.Bluetooth OBEX servers also publish their services in the servicediscovery database, which can be queried using the service discoveryprotocol (SDP) as you will see later in this set of Recipe 4.9.3.1.