quick_recipes (779892), страница 26
Текст из файла (страница 26)
. .TCommDbConnPref startPrefs;// Select bearers of type// GPRS and Wireless LAN onlystartPrefs.SetBearerSet(ECommDbBearerGPRS| ECommDbBearerWLAN);// Make sure the user is prompted with a list// of IAPs matching the preferencesstartPrefs.SetDialogPreference(ECommDbDialogPrefPrompt);// Start connection using our preferenceTRequestStatus status;conn.Start(startPrefs, status);// Wait for the connection to startUser::WaitForRequest(status);// Check if Start succeedTInt error = status.Int();// Do something. .
.// Close the connection and socket server sessionCleanupStack::PopAndDestroy(2);}146SYMBIAN C++ RECIPESDiscussion: The complete list of bearer sets is defined as part of theTCommDbBearer enumeration, defined in cdbcols.h.Note that, on UIQ, it is necessary to explicitly specify that the user willbe prompted with an IAP list dialog, done by setting the dialog preferenceto ECommDbDialogPrefPrompt in SetDialogPreference(). Thisavoids having the system automatically select the ‘preferred’ IAP, unlikeS60, where a list is always displayed.4.3.5.3Force a Connection to Use a Specific IAPAmount of time required: 15 minutesLocation of example code: \Networking\StartConnectionWithPrefsRequired library(s): esock.lib, commdb.lib, commsdat.libRequired header file(s): es_sock.h, commdbconnpref.h,metadatabase.h, commsdattypesv1_1.hRequired platform security capability(s): NetworkServicesProblem: You want to force a connection to use a specific Internet accesspoint (IAP).Solution: Load the IAP recordset and iterate through the recordset toretrieve information about each IAP record in CommsDat.
Set the userselected IAP id as a connection preference.#include <metadatabase.h> // CMDBSession (link to commsdat.lib)#include <commsdattypesv1_1.h> // CCDIAPRecord (link to commsdat.lib)using namespace CommsDat;void DisplayIAPListL(){// Open the comms repositoryCMDBSession* db = CMDBSession::NewLC(KCDVersion1_1);// Create a recordset (table) of IAPsCMDBRecordSet<CCDIAPRecord>* iapRecordSet= new(ELeave) CMDBRecordSet<CCDIAPRecord>(KCDTIdIAPRecord);CleanupStack::PushL(iapRecordSet);// Load the IAP recordset from the comms repositoryiapRecordSet->LoadL(*db);// Iterate through the recordsetCCDIAPRecord* iap = NULL;for (TInt i = 0; i < iapRecordSet->iRecords.Count(); ++i){// Get the IAP record (CCDIAPRecord)iap = static_cast<CCDIAPRecord*>(iapRecordSet->iRecords[i]);// We can now get information about the IAP.// For example,// iap->RecordId() gives us the IAP id and// iap->iRecordName gives us the humanNETWORKING147// readable name of the IAP}// Close the IAP recordset and the database sessionCleanupStack::PopAndDestroy(2); // iapRecordSet, db}void StartConnectionWithPrefsL(TInt aIapId){// Open socket server sessionRSocketServ ss;CleanupClosePushL(ss);User::LeaveIfError(ss.Connect());// Open connection on the socket server sessionRConnection conn;CleanupClosePushL(conn);User::LeaveIfError(conn.Open(ss));// Define the selection preferences.
. .TCommDbConnPref startPrefs;// Specify the IAP to usestartPrefs.SetIapId(aIapId);// Since we know which IAP we are using, it pays to// disable promptingstartPrefs.SetDialogPreference(ECommDbDialogPrefDoNotPrompt);// Start connection using our preferenceTRequestStatus status;conn.Start(startPrefs, status);// Wait for the connection to startUser::WaitForRequest(status);// Check if Start succeedTInt error = status.Int();// Close the connection and socket server sessionCleanupStack::PopAndDestroy(2);}Discussion: By implementing this in your application, you can storethe id of the IAP selected by the user and reuse it without promptingagain.
Note how IAP selection prompting has been disabled throughTCommDbConnPref::SetDialogPreference().Check commsdattypesv1_1.h for a list of standard records, including each record’s attributes.Note that, even though we explicitly created a recordset of type CCDIAPRecord, elements in iRecords need to be cast to the appropriatetype before usage, since iRecords is an RPointerArray of typeCMDBRecordBase.On the UIQ 3.0 SDK, commsdat.lib is missing for both winscwand armv5 targets. You can get hold of the library for both the targetsfrom the S60 3rd Edition SDK and use them in the UIQ SDK, whichshould work just fine.148SYMBIAN C++ RECIPESWhat may go wrong when you do this: Care should be taken whenstoring and reusing the IAP id, since the stored IAP can be deleted bythe user or not available, in which case, RConnection::Start()will fail.
In such a scenario, the application should have an option forthe user to select another IAP.4.3.5.4Resolve Domain NameAmount of time required: 15 minutesLocation of example code: \Networking\HostResolverRequired library(s): esock.lib, insock.libRequired header file(s): es_sock.hRequired platform security capability(s): NetworkServicesProblem: You want to resolve a domain name to its corresponding IPaddress, or resolve an IP address to its corresponding domain name, if ithas one.Solution: Use RHostResolver::GetByName() to resolve a domainname to its corresponding IP address and RHostResolver::GetByAddress() to resolve an IP address to its corresponding domain name,if it has one.// RSocketServ, RConnection et al (link to esock.lib)#include <es_sock.h>// KAfInet et al (link to insock.lib)#include <in_sock.h>// Host resolver daemon error codes#include <networking/dnd_err.h>void HostNameToAddressL(){// Open socket server sessionRSocketServ ss;CleanupClosePushL(ss);User::LeaveIfError(ss.Connect());// Initiate a connection// Open connection on the socket server sessionRConnection conn;CleanupClosePushL(conn);User::LeaveIfError(conn.Open(ss));TRequestStatus status;// Start the default connectionconn.Start(status);// Wait for the connection to startUser::WaitForRequest(status);NETWORKING149// Check if Start succeedUser::LeaveIfError(status.Int());// Connection started// Open the host resolver on the started connectionRHostResolver res;CleanupClosePushL(res);User::LeaveIfError(res.Open(ss, KAfInet, KProtocolInetUdp, conn));// Host name to resolve_LIT(KHostName, "www.symbian.com");// Define a TNameEntry instance that will receive the// resolved address.// TNameEntry is actually a packaged buffer that// wraps up TNameRecord in es_sock.hTNameEntry entry;User::LeaveIfError(res.GetByName(KHostName, entry));// Get the IP address of the hostTInetAddr hostAddr = entry().iAddr;// Now do the opposite, resolve host name using IP// address providedUser::LeaveIfError(res.GetByAddress(hostAddr, entry));// hostname and KHostName should be equal, if the reverse// DNS entry (PTR record) is correctly setup// for www.symbian.comTHostName hostName = entry().iName;// Close the host resolver, connection and socket server sessionCleanupStack::PopAndDestroy(3);}Discussion: The TNameEntry object passed on to the resolver functions is a packaged buffer of type TNameRecord.
Besides returningthe address/name, TNameRecord has an iFlags member of typeTNameRecordFlags that can be used to determine the origin of thequery response (see RFC1034).We can examine the error returned by the address/name functions todetermine whether the error was specific to DNS, listed in networking/dnd_err.h. KErrDndNameNotFound (-5120) implies the DNS server could not be contacted, possibly because an incorrect DNS serveraddress had been specified. KErrDndAddrNotFound (-5121) impliesthe address was not found in DNS records, possibly because an incorrecthost name was specified.RHostResolver::Next() can be called repeatedly till it returnsKErrNotFound to retrieve additional address(s)/name(s) associated witha host after the main name/address methods have been called.What may go wrong when you do this: The S60 3rd Edition SDK ismissing the networking/dnd.h file.
A simple solution is to copy150SYMBIAN C++ RECIPESit from the UIQ 3 SDK and place it in <s60 sdk install path>\epoc32\include\networking. The address family and protocolfields specified in RHostResolver::Open() must be KAfInet andKProtocolInetUdp respectively.4.3.5.5Use HTTP GET RequestAmount of time required: 20 minutesLocation of example code: \HTTP\HTTPGetRequired library(s): http.lib, bafl.lib, inteprotutil.libRequired header file(s): http.hRequired platform security capability(s): NetworkServicesProblem: You want to use HTTP GET requests.Solution: Create a transaction, specifying HTTP GET as method, alongwith the URI of the resource requested.// RHTTPSession et al.
(link to http.lib, bafl.lib, inetprotutil.lib)#include <http.h>void CGetPage::ConstructL(){// Open the HTTP session with// default protocol, e.g. HTTP over TCPiSession.OpenL();// Set generic headers, applicable to all// transactionsRHTTPHeaders httpHeaders = iSession.RequestSessionHeadersL();SetHeaderL(httpHeaders, HTTP::EUserAgent, KUserAgent);SetHeaderL(httpHeaders, HTTP::EAccept, KAccept);}void CGetPage::SetHeaderL(RHTTPHeaders aHeaders,TInt aHeaderField, const TDesC8& aHeader){RStringPool stringPool = iSession.StringPool();// Note that aHeader is user defined string, hence we// are responsible for freeing up the associated// RStringF object once we are done with it!RStringF header = stringPool.OpenFStringL(aHeader);CleanupClosePushL(header);THTTPHdrVal headerVal(header);aHeaders.SetFieldL(stringPool.StringF(aHeaderField,RHTTPSession::GetTable()), headerVal);CleanupStack::PopAndDestroy(&header);}NETWORKINGvoid CGetPage::GetPageL(const TDesC& aURL,MHTTPTransactionCallback& aTransCallback){// Convert URL to RFC3629 compliant// 8 bit UTF-8 encoded URIRBuf8 url8;CleanupClosePushL(url8);url8.CreateL(aURL.Length());url8.Copy(aURL);TUriParser8 uri;User::LeaveIfError(uri.Parse(url8));// Set method to HTTP GET and submit// the transaction.// Note that method is a pre-defined string in// the string pool, hence we don’t need to worry about// freeing it up, unlike user defined strings, see// SetHeaderL()RStringF method = iSession.StringPool().StringF(HTTP::EGET, RHTTPSession::GetTable());RHTTPTransaction transaction = iSession.OpenTransactionL(uri, aTransCallback, method);transaction.SubmitL();CleanupStack::PopAndDestroy(&url8);}void CHTTPGetPageAppUi::MHFRunL(RHTTPTransaction aTransaction,const THTTPEvent& aEvent){switch (aEvent.iStatus){case THTTPEvent::EGotResponseHeaders:// Examine the header receivedRHTTPResponse resp = aTransaction.Response();// Check status code.