×

Discussion Board

Results 1 to 10 of 10
  1. #1
    Regular Contributor
    Join Date
    Apr 2011
    Posts
    181

    Simultaneous writting and reading from a port

    Hi all
    I know that there has been similar post like this, but I don't get any useful answer yet. I the moderator is reading this post, I ask to not to remove the post.

    What is the best way to read from and write to a port simultaneously?

    I tried them with active object, but they were not effective. I also tried timers but they were not useful too.
    I also used threads but I faced some problems.

    Could you give me some help?
    O people of the world, Imam Hussein was killed in Karbala in thirsty.

  2. #2
    Nokia Developer Moderator
    Join Date
    Mar 2003
    Location
    Lempäälä/Finland
    Posts
    29,167

    Re: Simultaneous writting and reading from a port

    You might also give a bit more information. What port, which API are you using, and how.

    Also What does not effective mean ? and not useful, as well as what problems did you face ?

    if you want to get good answers, you should provided the necessary data first.

  3. #3
    Regular Contributor
    Join Date
    Apr 2011
    Posts
    181

    Re: Simultaneous writting and reading from a port

    thanks for your encouraging reply.
    My application gets voice from mic in form of TDesC and writes them to a port. At the same time, it reads data from the so-called port.

    1) I use this class(with some improvement) to work with DATAPORTs. It mainly uses a RComm object to work with ports.

    2) I used to create two CTranseiver objects, one for receiving data and another for sending. In the CTranseiver::RunL() if the state was receiving, I invoke the ReceiveL() again, and if the state was writing the SendL() was invoked. But when one of CTranseiver instances started to work, the other never started. (I think this is rational because active objects are pre-emptive.) If I want to use this application in a half duplex mode, this solution was enough.

    3) Additionally, I used two CPeridic object to invoke CTranseiver::SendL() or CTranseiver::ReceiveL() with different intervals. The problem was, the received voice was not clear with a lot of delay.

    4) At last, I made a new class that created a new thread and used a CTranseiver object to send or receive data, expect at this point I did not invoke SendL() or ReceiveL() in the CTranseiver::RunL(), but used an infinitive loop in the thread function to call them again. I approximately, used 9, 10 different ways to implement it, but they were not useful at all.

    I guess if the send or receive can work in a new thread properly, the problem is solved.
    Whats your idea?
    If you need more code, plz inform me. Regards.
    O people of the world, Imam Hussein was killed in Karbala in thirsty.

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

    Re: Simultaneous writting and reading from a port

    It can not be implemented symmetrically with a single class. You need 2 separate classes if you want to communicate on a single port object.

    Solution 1:
    the two classes are almost identical, but the second class has only a reference to the port "RComm &iComm;" and initializes it in the constructor
    Code:
    CReceiver::CReceiver(RComm &aComm,...):iComm(aComm)...
    {}
    (... stands for the other possible arguments you have)
    It is preferable that the CSender object owns the instance of CReceiver.

    Solution 2:
    The second object is just a minimal active object, exposing its functionality to CTransceiver (making SetActive and iStatus available so a second request becomes possible, and calling some CTransceiver method from its RunL and DoCancel, so the result and cleanup are also handled).

  5. #5
    Regular Contributor
    Join Date
    Apr 2011
    Posts
    181

    Re: Simultaneous writting and reading from a port

    Quote Originally Posted by wizard_hu_ View Post
    Solution 1:
    the two classes are almost identical, but the second class has only a reference to the port "RComm &iComm;" and ....
    I wrote like you said, but the problem is still unsolved, when one of CSender or CReceivers starts to works, the other active objects in the application can't work.
    I should move that objects to a new thread, could you help me to do so?
    O people of the world, Imam Hussein was killed in Karbala in thirsty.

  6. #6
    Regular Contributor
    Join Date
    Apr 2011
    Posts
    181

    Re: Simultaneous writting and reading from a port

    Hi again
    Since I wanted to do various thing simultaneously, I removed CSender and CReceiver to a new classes that run a RThread inside. Like this. Expect I use an CActiveScheduler after any Send() or Receive(). When one of send or receive thread starts to work, the other one can't work, but they work fine individually. I additionally tried below code, but it does not send or receive properly.
    Code:
    \
    void ThreadFunction(TAny* sender)
    {
     //
     // cleanup stack and active scheduler initialization omitted for clarity. 
     //
    
     TRequestStatus aStatus;
     while (ETrue)
     {
       if (host->iTransmitMode == ESend)
       {
          // iComm created locally before.
          iComm.ReadOneOrMore(aStatus, host->iReadBuffer);
          User::WaitForRequest(aStatus);
       }
       else  // ERead
       {
          iComm.Write(aStatus, host->data);
          User::WaitForRequest(aStatus);
       }
       User::After(host->iInterval);
     }
    What can be wrong?
    O people of the world, Imam Hussein was killed in Karbala in thirsty.

  7. #7
    Regular Contributor
    Join Date
    Apr 2011
    Posts
    181

    Re: Simultaneous writting and reading from a port

    Hi again
    the code in the last post is working now. I can send and receive data.
    At this point, how can I pass the received data to another thread in a safe manner?
    I used critical section in the object that receives data, but it wasn't useful. I get User 0 error.
    O people of the world, Imam Hussein was killed in Karbala in thirsty.

  8. #8
    Nokia Developer Moderator
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    28,674

    Re: Simultaneous writting and reading from a port

    Sorry, I have not seen this thread for a while.

    I do not really want to find out reliable ways to share unsharable objects between threads (you found that RCommServ does not tolerate ShareAuto), and then reliably keep data flowing between them.
    I use a pair of active objects, where one of them is just a "skeleton" actually:
    Code:
    // HelperActive.h
    #ifndef __HELPER_ACTIVE_H__
    #define __HELPER_ACTIVE_H__
    
    class MHelperObserver
    {
    public:
        virtual void HelperRunL()=0;
        virtual void HelperDoCancel()=0;
    };
    
    #include <e32base.h>
    
    class CHelperActive : public CActive
    {
    public:
        CHelperActive(MHelperObserver &aObserver);
        ~CHelperActive();
    
        void SetActive();
        
        void DoCancel();
        void RunL();
    
    private:
        MHelperObserver &iObserver;
    };
    
    #endif
    Code:
    // HelperActive.cpp
    #include "HelperActive.h"
    
    CHelperActive::CHelperActive(MHelperObserver &aObserver) : CActive(EPriorityStandard)
    ,iObserver(aObserver)
    {
        CActiveScheduler::Add(this);
    }
    
    CHelperActive::~CHelperActive()
    {
        Cancel();
    }
    
    void CHelperActive::DoCancel()
    {
        iObserver.HelperDoCancel();
    }
    
    void CHelperActive::RunL()
    {
        iObserver.HelperRunL();
    }
    
    void CHelperActive::SetActive()
    {
        CActive::SetActive();
    }
    so it simply makes available its iStatus and SetActive to its owner and invokes a RunL and a DoCancel-like method using the MHelperObserver mixin.

    Then an actual class using this is
    Code:
    CTCPClientActive::CTCPClientActive(CSocketStore &aSocketStore) : CActive(EPriorityStandard), iSocketStore(aSocketStore)
    {}
    
    CTCPClientActive* CTCPClientActive::NewL(CSocketStore &aSocketStore,TUint32 aAddress,TUint16 aPort)
    {
        CTCPClientActive* self = new(ELeave) CTCPClientActive(aSocketStore);
        CleanupStack::PushL(self);
        self->ConstructL(aAddress,aPort);
        CleanupStack::Pop();
        return self;
    }
    
    void CTCPClientActive::ConstructL(TUint32 aAddress,TUint16 aPort)
    {
        CActiveScheduler::Add(this);
        iSendBuf=CBufFlat::NewL(1);
        iRecvBuf=CBufFlat::NewL(1);
        iHelper=new(ELeave)CHelperActive(*this);
        User::LeaveIfError(iSocket.Open(iSocketStore.iSocketServ,KAfInet,KSockStream,KProtocolInetTcp,iSocketStore.iConnection));
        iInetAddr.SetAddress(aAddress);
        iInetAddr.SetPort(aPort);
        iSocket.Connect(iInetAddr,iStatus);
        SetActive();
        iSendState=ESendConnecting;
        iSocketStore.iClients.InsertInAddressOrderL(this); // do not leave after this line (ConsturctL: 'this' is also on the Cleanup Stack)
    }
    
    CTCPClientActive::~CTCPClientActive()
    {
        Cancel();
        delete iHelper;
        iSocket.Close();
        delete iSendBuf;
        delete iRecvBuf;
    }
    
    void CTCPClientActive::DoCancel()
    {
        switch(iSendState)
        {
        case ESendConnecting:
            iSocket.CancelConnect();
            break;
            
        case ESendSend:
            iSocket.CancelWrite();
            break;
        }
    }
    
    void CTCPClientActive::RunL()
    {
        if(iStatus!=KErrNone)
        {
            ...
        }
        if (iStatus == KErrNone)
        {
            switch(iSendState)
            {
            case ESendConnecting:
                StartRecv();
                iSendState=ESendIdle; // server-side sends the first message (Hello)
                break;
                
            case ESendSend:
                iSendState=ESendIdle;
                iSendBuf->Delete(0,iSendData.Size());
                TrySend();
                break;
            }
        }
    }
    
    void CTCPClientActive::HelperDoCancel()
    {
        switch(iRecvState)
        {
        case ERecvRecv:
            iSocket.CancelRecv();
            break;        
        }
    }
    
    void CTCPClientActive::HelperRunL()
    {
        if(iHelper->iStatus!=KErrNone)
        {
            ...
        }
        if (iHelper->iStatus == KErrNone)
        {
            switch(iRecvState)
            {
            case ERecvRecv:
                iRecvBuf->InsertL(iRecvBuf->Size(),iRecvData);
                iRecvBuf->Delete(0,iTransfer->ReceiveL(iRecvBuf->Ptr(0)));
                if(iTransfer->state==TX_CLOSING && iSendState==ESendIdle)
                    ShutDownL(_L("TX_CLOSING"));
                else
                    StartRecv();
                break;        
            }
        }
    }
    
    void CTCPClientActive::StartRecv()
    {
        iSocket.RecvOneOrMore(iRecvData,0,iHelper->iStatus,iSockXfrLength);
        iHelper->SetActive();
        iRecvState=ERecvRecv;
    }
    
    void CTCPClientActive::SendL(const TDesC8 &aMessage)
    {
        iSendBuf->InsertL(iSendBuf->Size(),aMessage);
        TrySend();
    }
    
    void CTCPClientActive::TrySend()
    {
        if(iSendState!=ESendIdle)
            return;
        if(iSendBuf->Size()==0)
        {
            if(iTransfer->state==TX_CLOSING)
                ShutDownL(_L("TX_CLOSING"));
            return;
        }
        iSendData.Set(iSendBuf->Ptr(0));
        iSocket.Write(iSendData,iStatus);
        SetActive();
        iSendState=ESendSend;
    }
    "main" class connects and sends data (when available), while the "Helper" part is receiving data on the same RSocket object all the time.

  9. #9
    Regular Contributor
    Join Date
    Apr 2011
    Posts
    181

    Re: Simultaneous writting and reading from a port

    Hi wizard_hu_
    Thanks for your informative code. I have two questions:
    1) In your code, the receiver of data is CTCPClientActive and the CHelperActive just carry the burden of receiving the new data from socket, the actual user of it, is CTCPClientActive. Am I right?

    2) Is it functional to implement your design method in my code, considering I should preferably make everything local in the thread function?
    O people of the world, Imam Hussein was killed in Karbala in thirsty.

  10. #10
    Nokia Developer Moderator
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    28,674

    Re: Simultaneous writting and reading from a port

    1) CHelperActive is used for handling the receive request only. Everything happens in the other class.
    2) I took this code from an actual project (just cut it back a little, that is why "iTransfer" appears from nowhere in the middle of HelperRunL), and it works for me.

Similar Threads

  1. Real time writting to and reading from a port
    By ehsanTC in forum Symbian
    Replies: 5
    Last Post: 2011-11-13, 14:20
  2. Reading the USB port
    By runfastman in forum Mobile Java General
    Replies: 0
    Last Post: 2009-01-30, 20:16
  3. Reading SMS from port.
    By prafulpijdurkar in forum Mobile Java General
    Replies: 2
    Last Post: 2008-06-10, 14:32
  4. Reading and writting with buffers in J2ME
    By magnetic in forum Mobile Java General
    Replies: 5
    Last Post: 2007-01-11, 15:27

Posting Permissions

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