×

Discussion Board

Results 1 to 5 of 5
  1. #1
    Registered User
    Join Date
    Jul 2007
    Posts
    26

    Exclamation Http client with CActive object

    Hi,

    I'm trying to convert the sample synchronous http example client to asynchronous with CActive object.

    I'm trying to build a DLL.
    The app registers a callback and calls the exported function in the DLL.
    the function should make a http request and return immediately without waiting for response.
    After receiving the server response, the DLL should send the response to the app with callback.

    I've the following code:
    class CHttpClient : public CBase, public MHTTPTransactionCallback
    {
    public:
    static CHttpClient* NewL();
    ~CHttpClient();

    void InvokeHttpMethodL(const TDesC8& aUri, TRequestStatus& aStatus);
    void CancelTheRequest();

    // methods inherited from MHTTPDataSupplier
    virtual TBool GetNextDataPart(TPtrC8& aDataPart);
    virtual void ReleaseData();
    virtual TInt OverallDataSize();
    virtual TInt Reset();

    protected:
    CHttpClient();
    void ConstructL();

    private: // Functions from base classes

    void MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent);
    TInt MHFRunError(TInt aError, RHTTPTransaction aTransaction, const THTTPEvent& aEvent);

    void SetHeaderL(RHTTPHeaders aHeaders, TInt aHdrField, const TDesC8& aHdrValue);
    void GetRequestBodyL(RStringF& aMethod);

    RHTTPSession iHttpSession;
    RHTTPTransaction iTransaction;

    TBool iSavingResponseBody;
    RFs iFileServ;
    RFile iRespBodyFile;
    TFileName iRespBodyFileName;
    TParse iParsedFileName;
    MHTTPDataSupplier* iRespBody;
    };

    class CActiveHttpObj : public CActive
    {
    public: // New functions

    static CActiveHttpObj* NewL(CHttpClient* aHttpClient);
    ~CActiveHttpObj();

    void RequestURL(const TDesC8& aUri);

    private:
    CActiveHttpObj(CHttpClient* aHttpClient);
    void ConstructL();

    private: // Functions from base classes
    void RunL();
    void DoCancel();

    TInt RunError(TInt aError);

    private: // Data members

    CHttpClient* iHttpClient;

    };

    ////

    void CActiveHttpObj::RunL()
    {
    if (iStatus == KErrNone)
    {
    TRequestStatus* status = &iStatus;
    User::RequestComplete( status, KErrNone );
    }
    }
    ///
    void CActiveHttpObj::RequestURL(const TDesC8& aUri)
    {
    iStatus = KRequestPending;
    if (IsActive())
    {
    return;
    }

    iHttpClient->InvokeHttpMethodL(aUri, iStatus);
    SetActive();
    }
    ///
    in my exported function()

    {
    CActiveScheduler* scheduler = new(ELeave) CActiveScheduler();
    CleanupStack::PushL(scheduler);
    CActiveScheduler::Install(scheduler);

    // Create and start the client
    CHttpClient* httpCli = CHttpClient::NewL();
    CActiveHttpObj* httpobj = CActiveHttpObj::NewL(httpCli);
    httpobj->RequestURL(url);
    CActiveScheduler::Start();
    printf("\n done downloading");
    CleanupStack::PopAndDestroy(2);

    }
    //////////////

    It's still a blocking call. I don't see the printf until the request completes. How do I make it asynchronous? Do I need to create a thread and call CActiveScheduler::Start() from that thread?

    I didn't change the code in CHttpClient::MHFRunL ().
    Do I need any more changes? Could someone please tell me where is the mistake?

    Thanks in advance,
    jvinjam

  2. #2
    Super Contributor
    Join Date
    Jul 2007
    Location
    ShenZhen, China
    Posts
    4,346

    Re: Http client with CActive object

    hi jvinjam, ur code has a problem. it is a bad way that new and install CActiveScheduler.
    CActiveScheduler::Start will begin AO service loop, it will not return until some AO stop CActiveSchedule.

    if your caller app is GUI, u not need new CActiveScheduler, if your caller app is console app, the console app need new and install, start CActiveScheduler.

    for generic way.
    in CActiveHttpObj::CActiveHttpObj,
    {
    CActiveScheduler::Add( this );
    }

    and in your export func, only need
    {

    // Create and start the client
    CHttpClient* httpCli = CHttpClient::NewL();
    CActiveHttpObj* httpobj = CActiveHttpObj::NewL(httpCli);
    httpobj->RequestURL(url);
    }

    ps. your CleanupStack code need some change.
    ----------------------------
    坚持学习, 坚持编码
    http://www.devdiv.net/
    qxiaoyuan

  3. #3
    Registered User
    Join Date
    Jul 2007
    Posts
    26

    Re: Http client with CActive object

    1. So, after SetActive() call in my function, don't I need CActiveScheduler::Start() call?
    I tried to delete this line. Then nothing happens.

    2. I've a break point in my active object's RunL(). But, it never gets there.

    void CActiveHttpObj::RunL()
    {
    if (iStatus == KErrNone)
    {
    TRequestStatus* status = &iStatus;
    User::RequestComplete( status, KErrNone );
    }
    else
    {
    User::Leave(iStatus.Int());
    }
    }

    Am I doing something wrong? Since I've MHFRunL() in my client, the active object's RunL() never gets called!

    I'm little confused. Which one of the following is correct?
    (a). Once the request completes, active scheduler calls the RunL() method of active object, which in turn should call MHFRunL()
    !b). active scheduler calls client's MHFRunL() and active object's RunL() doesn't do anything

    3. Should this call- CleanupStack::PopAndDestroy(3) fix my cleanup code?

    Thanks,
    jvin

  4. #4
    Nokia Developer Moderator
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    28,684

    Re: Http client with CActive object

    It is not clear what you are doing, and what CHttpClient is.
    However some notes:
    - CActiveScheduler::Start starts the Active Scheduler loop
    - CActiveScheduler::Start will return when someone invokes CActiveScheduler::Stop
    - when the loop is running, CActive::RunL methods of active objects are going to be executed, when requests issued by those active objects are completed:
    -- iStatus != KRequestPending (since KRequestPending explicitly means that the request is not complete)
    -- SetActive has been invoked (since SetActive marks the active object to be waiting for something)
    - your code resembles to be a self-completing active object (when you are the one who completes iStatus via User::RequestComplete), however SetActive is missing
    - even if you put SetActive there, nothing is going to happen, just your RunL method will be invoked from time to time forever
    - self-completing active objects are used for de-composing long running tasks (like loops), without using threads - a series of examples of that is provided in Examples\Base\IPC\Async\Fibonacci1-2-3: 1 is synchronous, 2 uses a thread, 3 uses self-completing AO
    - for RHTTPXy classes you do not need an explicit active object, since events are going to be delivered to you via an M-class, an interface. It is usual in Symbian that you either have to create an active object or implement an interface. In the latter case an active object is hidden inside the given API, and that active object is going to invoke your callback method - so you do not have to write an own AO
    - since such callbacks provided via M-classes are still result of activity of active objects, you still need the Active Scheduler: simply issue your request, then invoke CActiveScheduler::Start. When the transaction is complete, invoke CActiveScheduler::Stop from MHFRunL
    Note that recent SDK-s contain HTTP examples for both the console-based case (Examples\AppProts\exampleclient, where you can check explicit usage of CActiveScheduler) and for the GUI-case (S60CppExamples\WebClient, S60CppExamples\AutoAdaptedToTouchEx\WebClient or S60Ex\WebClient - depending on the SDK you use -, where CActiveScheduler is invisible, since every GUI application runs inside an Active Scheduler loop)

  5. #5
    Registered User
    Join Date
    Jul 2007
    Posts
    26

    Re: Http client with CActive object

    I thought that if I use CActive object, I don't need to call CActiveScheduler::Start(). Thanks for the clarification.

    jvinjam

Similar Threads

  1. Nested CActive Object
    By yuenfatt in forum Symbian
    Replies: 4
    Last Post: 2008-09-08, 09:34
  2. Passing object from server to client
    By bjorn.rudolfsson in forum Symbian
    Replies: 3
    Last Post: 2008-08-27, 13:21
  3. HTTP Post problem on Symbian 9.2 - TCP stuck?
    By bgenady in forum Symbian Networking & Messaging (Closed)
    Replies: 0
    Last Post: 2008-08-04, 19:33
  4. How to use CActive Object for CTelephony
    By saadmansur in forum Symbian Networking & Messaging (Closed)
    Replies: 4
    Last Post: 2007-04-27, 11:31
  5. access points problem with HTTP client api
    By Svat_ in forum Symbian
    Replies: 1
    Last Post: 2006-12-26, 16:19

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
×