How to Make an HTTP Connection Using TCP/IP with RSocket

Reviewer Approved    
The following code shows how to make an HTTP connection using a TCP/IP with RSocket interface which will retrieve a Web page by resolving the IP address of a server, constructing an HTTP request, sending it to the server and then receiving the response.
The sample code will show you how to:
 Open a socket and resolve the host name
 Perform the HTTP GET operation
 Display the HTTP GET status and data to the user
Note! This example does NOT send the HTTP host header so if the URL you're trying to load is on a virtual server, it won't work. Also as it says on the comments, it will disregard all file path information and converts all data into 16bit text, so it needs a lot of work to make it useful.


#include <e32std.h>
#include <es_sock.h>
#include <in_sock.h>
#include <Uri16.h>
 
//Two Phase Construction
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;
}
 
// second-phase constructor
void CRetrieveHttp::ConstructL()
{
 iState = EIdle ;
 
 // Add self to active scheduler
 CActiveScheduler::Add(this) ;
 
 // Connect to socket server
 User::LeaveIfError (iSockServer.Connect()) ;
 
}
 
 
// Constructor and destructor
CRetrieveHttp::CRetrieveHttp(MRetrieveHttpCallbacks& aCallback) :
CActive(0), iCallbacks (aCallback) 
{
 iState = EIdle ;
}
 
CRetrieveHttp::~CRetrieveHttp()
{
 iSockServer.Close() ;
}

// Request function - Validates URL, parses out server name
// Any extra url info is ignored, port is assumed to be 80
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"));
 
 // 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 the main function, 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)
  {
 
   // 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))
   {
 
    iState =EFailed ;
    finished = ETrue ;
   }
   else
   {
    iState = EConnecting ;    
    iSocket.Connect(address, iStatus) ;
   }
  }
  else
  {
 
   iState = EFailed ;
   finished = ETrue ;
  }
  break ;
 
    case EConnecting:
    // Socket sucessfully opened. Send preconstructed request to server,
    // and advance state to ESending
  if (iStatus == KErrNone)
  {
   iSocket.Write(iRequest, iStatus) ;
   iState = ESending ;  
  }
  else
  {
   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)
         {
        //iResponseLength = 0 ;
        iSocket.RecvOneOrMore(iResponseChunk, 0, iStatus, iResponseChunkSizePkg) ;
        iState = EReceiving ;
         }
         else
  {
 
   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)
  {
  // 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];
                                // HTTP uses /r/n line termination,
                                //which looks funny in a CEikLabel
    if (ch != '/r')
                                    iResponse.Append (iResponseChunk[copyPtr]);                           
                        }
   if (iResponse.Length() == iResponse.MaxLength())
   {
   // Response buffer full
    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
  {
   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() ;
 }
 
 
//Method to get at the retrieved data.
TDesC &CRetrieveHttp::GetResponseData()
{
 return iResponse ;
}

 

FYI: This was coded and tested on Sony Ericsson P800/P900.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值