Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3472426
  • 博文数量: 1450
  • 博客积分: 11163
  • 博客等级: 上将
  • 技术积分: 11101
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-25 14:40
文章分类

全部博文(1450)

文章存档

2017年(5)

2014年(2)

2013年(3)

2012年(35)

2011年(39)

2010年(88)

2009年(395)

2008年(382)

2007年(241)

2006年(246)

2005年(14)

分类: C/C++

2009-08-14 13:43:08

1 打开一个会话
Http客户端会话由声明一个RHttpSession对象并调用它的OpenL()方法开始。
RHTTPSession iSession;
iSession.OpenL();
2 创建一个事务
要创建一个新的事务,客户端必须指定URI、HTTP请求方法和一个用于接收事务处理期间的事件的callback对象,该回调对象必须继承自MHTTPTransactionCallBack接口。RHTTPTransaction句柄由唯一地定义新事物的会话返回。
void CHttpClient::InvokeHttpMethodL(const TDesC8& aUri, RStringF aMethod)
{
...
TUriParser8 uri;
uri.Parse(aUri);
RHTTPTransaction trans = iSession.OpenTransactionL(uri, *iTransObs, aMethod);
...
};
OpenTransactionL()的第二个参数表示回调对象。
3 设置请求头
在打开了事务之后,如果有需要,客户端就要设置请求头。但是,对于简单事务来说,请求头的使用是可选的,因为HTTP/1.1的请求头会被自动生成。
可以使用RHTTPHeaders类访问与事务请求或事务响应相关的头部。该句柄是从事务相关的RHTTPRequest或RHTTPResponse对象中取得的。
RHTTPHeaders hdr = trans.Request().GetHeaderCollection();
// Add headers appropriate to all methods
SetHeaderL(hdr, HTTP::EUserAgent, KUserAgent);
SetHeaderL(hdr, HTTP::EAccept, KAccept);
...

void CHttpClient::SetHeaderL(RHTTPHeaders aHeaders, TInt aHdrField, const TDesC8& aHdrValue)
{
RStringF valStr = iSession.StringPool().OpenFStringL(aHdrValue);
THTTPHdrVal val(valStr);
aHeaders.SetFieldL(iSession.StringPool().StringF(aHdrField), val);
valStr.Close();
}

头部域类型是使用HTTP名字空间的枚举来指定,如:HTTP::EUserAgent。该类用于拥有头部域的值:THTTPHdrVal,就像一个C++联合类型,在其中它可以拥有不同的数据类型。
4 启动事务
设置了头部域后,一个不带请求体的简单事务就可以立即启动了。但这只是适用于诸如GET、HEAD和TRACE等HTTP方法的情况。而不适用于另外一些请求中包括主体的HTTP方法,如POST。客户端向其发送请求体数据的数据提供者必须在事务启动之前关联到事务上。
当事务准备启动时,客户端调用RHTTPTransaction::SubmitL()表示请求应该被提交了。
...
// submit the transaction
trans.SubmitL();
// Start the scheduler, once the transaction completes or is cancelled //on an error the scheduler will be stopped in the event handler
CActiveScheduler::Start();
5 接收事务事件
当客户端从HTTP服务器收到数据,事件也会被生成并通过会话过滤器传回到客户端。事件到达客户端时,HTTP会唤醒事务回调对象,也即MHFRunL (RHTTPTransaction aTransaction, const THTTPEvent &aEvent)方法。
在该方法中可通过以下方式利用事务响应取得响应状态码和文本描述:
case THTTPEvent::EGotResponseHeaders:
{
RHTTPResponse resp = aTransaction.Response();
TInt status = resp.StatusCode();
RStringF statusStr = resp.StatusText();
下面的代码则是使用THTTPHdrFieldIter类循环取得头部域数据:
    RHTTPResponse resp = aTrans.Response();
    RStringPool strP = aTrans.Session().StringPool();
    RHTTPHeaders hdr = resp.GetHeaderCollection();
    THTTPHdrFieldIter it = hdr.Fields();
    TBuf fieldName16;
    TBuf fieldVal16;

    while (it.AtEnd() == EFalse)
    {
    // Get the name of the next header field
    RStringTokenF fieldName = it();
    RStringF fieldNameStr = strP.StringF(fieldName);

    // Check it does indeed exist
    THTTPHdrVal fieldVal;
    if (hdr.GetField(fieldNameStr,0,fieldVal) == KErrNone)
      {
       ...
       // Display realm for WWW-Authenticate header
       RStringF wwwAuth = strP.StringF(HTTP::EWWWAuthenticate, RHTTPSession::GetTable());
       if (fieldNameStr == wwwAuth)
         {
         // check the auth scheme is 'basic'
         RStringF basic = strP.StringF(HTTP::EBasic,RHTTPSession::GetTable());
         RStringF realm = strP.StringF(HTTP::ERealm, RHTTPSession::GetTable());
         THTTPHdrVal realmVal;
         if (fieldVal.StrF() == basic)
          // check the header has a 'realm' parameter 
          if (hdr.GetParam(wwwAuth, realm, realmVal) == KErrNone)
           {
           RStringF realmValStr = strP.StringF(realmVal.StrF());
           fieldVal16.Copy(realmValStr);
           Printf(_L("Realm is: %S\n"), &fieldVal16);
           }
        }
     }
     // Advance the iterator
     ++it;
}

6 取得响应体
要取得响应体,就必须使用包含在事务响应里的数据提供者。在客户端完成处理所有的响应体数据片后,必须数据释放数据提供者。
case THTTPEvent::EGotResponseBodyData:
{
// Some (more) body data has been received. Get the body data supplier
MHTTPDataSupplier* body = aTransaction.Response().Body();
TPtrC8 dataChunk;
TBool isLast = body->GetNextDataPart(dataChunk);
Dump(dataChunk);
if (isLast)
   Printf(_L("Got the last data chunk.\n"));
// Done with that bit of body data
body->ReleaseData();
}
break;
7 完成事务
事务的完成(不管是成功还是失败),都要停止本地活动调度器。枚举值EResponseComplete仅是事务完成的一个信号,而不用于完成任何具体的工作。具体的工作放在成功或是失败的分支里处理:
case THTTPEvent::EResponseComplete:
    {
    // The transaction's response is complete
    Printf(_L("\nTransaction Complete\n"));
    }
    break;
case THTTPEvent::ESucceeded:
    {
    Printf(_L("Transaction Successful\n"));
    aTransaction.Close();
    CActiveScheduler::Stop();
    }
    break;
case THTTPEvent::EFailed:
    {
    Printf(_L("Transaction Failed\n"));
    aTransaction.Close();
    CActiveScheduler::Stop();
    }
    break;
最后要使用RHTTPTransaction::Close()关闭事务,这个调用将释放所有关联到事务的资源。
8 终止会话
客户端准备终止时,要关闭会话:
CHttpClient::~CHttpClient()
    {
    iSession.Close();
    ...
    }
关闭会话导致所有的资源被返回给系统,所有残存的未完成事务都将被立即取消。
阅读(553) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~