⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcpexactive.cpp

📁 关于symbian uiq平台的例子不多
💻 CPP
字号:
#include <e32std.h>
#include <es_sock.h>
#include <in_sock.h>
#include <Uri16.h>
#include "TCPExActive.h"

namespace // anon
	{

	#if defined(_DEBUG)
	_LIT (KDebugMsgResolved,"Resolved") ;
	_LIT (KDebugMsgResolveFailed,"Not Resolved") ;
	_LIT (KDebugMsgOpenFailed,"Can't Open") ;
	_LIT (KDebugMsgConnecting, "Connecting") ;
	_LIT (KDebugMsgConnectFailed, "Can't Connect") ;
	_LIT (KDebugMsgSending, "Sending") ;
	_LIT (KDebugMsgSendFailed, "Send Failed");
	_LIT (KDebugMsgReceiving, "Receiving") ;
	_LIT (KDebugMsgReceivedChunk, "Received a chunk") ;
	_LIT (KDebugMsgReceiveFailed, "Receive Failed") ;
	#endif // ifdef _DEBUG

	} // anon namespace

//
// The usual Symbian OS two-phase construction stuff
//
CRetrieveHttp* CRetrieveHttp::NewL(MRetrieveHttpCallbacks& aCallback)
	{
	CRetrieveHttp* self=NewLC(aCallback);
	CleanupStack::Pop(self);
	return self;
	}

CRetrieveHttp* CRetrieveHttp::NewLC(MRetrieveHttpCallbacks& aCallback)
	{
	CRetrieveHttp* self = new(ELeave) CRetrieveHttp(aCallback);
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
	}

void CRetrieveHttp::ConstructL() // second-phase constructor
	{
	iState = EIdle ;

	// Add self to active scheduler
	CActiveScheduler::Add(this) ;

	// Connect to socket server
	User::LeaveIfError (iSockServer.Connect()) ;
	
    }


//
// Standard C++ constructor and destructor
//
CRetrieveHttp::CRetrieveHttp(MRetrieveHttpCallbacks& aCallback) : CActive(0), iCallbacks (aCallback)  // first-phase C++ constructor
	{
	iState = EIdle ;
 	}
 	
CRetrieveHttp::~CRetrieveHttp() 
	{
	iSockServer.Close() ;
	}



//
// Request function - Does a bit of validation on the URL, parses out server name
// Any extra url info is ignored, port is assumed to be 80 and resource is assumed to
// be /
//  
void CRetrieveHttp::RequestL(const TDesC& aURL)
	{
	
	TUriParser url;
	url.Parse(aURL);
	
	if (url.Extract(EUriScheme).Compare(_L("http")) != 0)
		{
			// Invalid URL - didn't start with "HTTP://"
			User::Leave(KErrArgument) ;
		}
	
	// Clear response strings	
	iResponse.Zero() ;
	iResponseChunk.Zero() ;
	
	iServerName.Copy(url.Extract(EUriHost));
	
	// Construct HTTP: GET command
	iRequest.Copy(_L8("GET / HTTP/1.0\r\n\r\n"));
	
#ifdef _DEBUG
	User::InfoPrint (iServerName) ;
#endif

	// Open resolver socket
	User::LeaveIfError (iResolver.Open(iSockServer, KAfInet, KProtocolInetTcp)) ;
		
	// Attempt to resolve name
	iResolver.GetByName(iServerName, iHostAddress, iStatus) ; 
	
	// Move to next state
	iState = EResolving ;
	
	// Enable the active object
	SetActive() ;
	}	
	




//
// Mandatory RunL from CActive - This is where it all happens, basically a big switch
// statement that implements a state machine that goes through all the stages of
// performing the "GET" operation
//
void CRetrieveHttp::RunL()
	{
	TBool finished = EFalse ;
	
	switch (iState)
		{
		case EIdle:
			// Shouldn't happen
			break ;
			
		case EResolving:
			// Name resolution completed - check result, if OK open socket
			// and advance state to EOpening 
			if (iStatus == KErrNone)
				{
#ifdef _DEBUG
				User::InfoPrint (KDebugMsgResolved) ;
#endif

				// Recover server's IP address
				TInetAddr address ;
				address = iHostAddress().iAddr;
				address.SetPort (80) ; // Assume always port 80 for now!
				
				// Attempt to open the socket
				if (iSocket.Open(iSockServer, KAfInet, KSockStream, KProtocolInetTcp))
					{
#ifdef _DEBUG
					User::InfoPrint (KDebugMsgOpenFailed) ;
#endif
					iState =EFailed ;
					finished = ETrue ;
					}
				else
					{
#ifdef _DEBUG
					User::InfoPrint (KDebugMsgConnecting) ;
#endif
					iState = EConnecting ;				
					iSocket.Connect(address, iStatus) ;
					}
				}
			else
				{
#ifdef _DEBUG
				User::InfoPrint (KDebugMsgResolveFailed) ;
#endif
				iState = EFailed ;
				finished = ETrue ;
				}
			break ;
			
		case EConnecting:
			// Socket sucessfully opened. Send preconstructed request to server,
			// and advance state to ESending
			if (iStatus == KErrNone)
				{
#ifdef _DEBUG
					User::InfoPrint(KDebugMsgSending) ;
#endif
					iSocket.Write(iRequest, iStatus) ;
					iState = ESending ;		
				}
			else
				{
#ifdef _DEBUG
				User::InfoPrint(KDebugMsgConnectFailed) ;
#endif
				iState = EFailed ;
				finished = ETrue ;
				}	
			break ;
			
		case ESending:
			// Request sent, Start receive process for first "chunk" of
			// data and advance state to EReceiving
			if (iStatus == KErrNone)
				{
#ifdef _DEBUG
				User::InfoPrint (KDebugMsgReceiving) ;
#endif
				//iResponseLength = 0 ;
				iSocket.RecvOneOrMore(iResponseChunk, 0, iStatus, iResponseChunkSizePkg) ; 
				iState = EReceiving ;
				}
			else
				{
#ifdef _DEBUG
				User::InfoPrint (KDebugMsgSendFailed) ;
#endif
				iState = EFailed ;
				finished = ETrue ;
				}	
			break ;
			
		case EReceiving:
			// If we sucessfully got a chunk then ask for more, if we've
			// finished then go to complete
			if (iStatus == KErrNone)
				{
#ifdef _DEBUG
				User::InfoPrint (KDebugMsgReceivedChunk) ;
#endif
				// Copy 8 bit characters into 16 bit response buffer
				for(TInt copyPtr = 0; (copyPtr < iResponseChunk.Length()) && (iResponse.Length() < iResponse.MaxLength()); copyPtr++)
					{
					TChar ch = iResponseChunk[copyPtr];
					if (ch != '\r') // HTTP uses \r\n line termination, which looks funny in a CEikLabel
						iResponse.Append (iResponseChunk[copyPtr]) ; 			
					}
				if (iResponse.Length() == iResponse.MaxLength()) 
					{
					// Response buffer full - We'll call that a sucess and pass back what we got anyway!
					iState = EComplete ;
					finished = ETrue ;
					}
				else
					{
					// Issue another read request
					iResponseChunk.Zero() ;
					iSocket.RecvOneOrMore(iResponseChunk, 0, iStatus, iResponseChunkSizePkg) ; 
					}
				}
			else if (iStatus == KErrEof)
				{
					// Server has no more data to send - We've finished!
					iState = EComplete ;
					finished = ETrue ;
				}
			else
				{
#ifdef _DEBUG
				User::InfoPrint (KDebugMsgReceiveFailed) ;
#endif
				iState = EFailed ;
				finished = ETrue ;
				}
			break ;

		// Either retrieve completed or oops! Close all sockets and
		// free resources either way.			
		case EComplete:
		case EFailed:
			finished = ETrue ;
			break ;
		}
		
	// Notify our "owner" of state change
	iCallbacks.StateChange(iState) ;

	if (finished)
		DoCancel() ;
	else
		SetActive() ;
	}



//
// Mandatory DoCancel - from CActive
//
void CRetrieveHttp::DoCancel()
	{
	// Close everything that might be open and cancel any outstanding
	// operations.
	iResolver.Close() ;
	iSocket.CancelAll() ;
	iSocket.Close() ;
	}
	

//
// Very boring access method to get at the retrieved data.
//
TDesC &CRetrieveHttp::GetResponseData()
{
	return iResponse ;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -