prob with active objects .. for TCP sockets ..

Login to reply to this topic.
Wed, 2003-09-17 13:53
Joined: 2003-09-17
Forum posts: 4
Hi All ,

I was writing  a test code for testing TCP sockets active and passive connection .

I have two active objects  created  and both binded two different ports on same IP address ( 127.0.0.1 )

one object (Passive) ilistens .. and other object (active) connects with port address of  passive one .  both connect and listen done  during the construction of each objects.

when i test this code .. the prob is .. the RUNL of only one active objects is called  at ONE time . RUNL of other is not called at all..

Listen request of  Passive  completes and in RUNL of Passive is called  where my accept  request completes successfully . BUT
RUNL of Active is never called ( which should be called  when Connect Request Completes)  and if increase priority of active then passive RUNL is not called ...

Where ia m going wrong .. Please see the Code..

Thanks in Adv...

Puneet

.
Code:

Passive AO::Open(src_ip,src_port)
{

...
err=iSession.Connect();
User::LeaveIfError(err);
     
      err = iListen.Open(iSession, KAfInet,KSockStream, KProtocolInetTcp);

         User::LeaveIfError(err);

        //blank socket

         err = iSocket.Open(iSession);

         User::LeaveIfError(err);

           // Bind the listening socket to the required

         // port.

         TInetAddr Addr_Passive(src_ip, src_port);

         iListen.Bind(Addr_Passive);

         // Listen for incoming connections...
       
         iListen.Listen(2);
         SetActive();

..Passive RUNL code ...
{
....
 iListen.Accept(*iSock, iStatus);

      User::WaitForRequest(iStatus);
...
}

Active Object::Open(.....)
{
 iSocket = new RSocket();
CActiveScheduler::Add(this);
err=iSession.Connect();
User::LeaveIfError(err);
       err = iSocket->Open(iSession, KAfInet,KSockStream, KProtocolInetTcp);

       User::LeaveIfError(err);
TInetAddr Addr_Active_Dest(dest_ip,dest_port);
        iSocket->Connect(Addr_Active_Dest,iStatus);
        SetActive();
   }

Active AO RUNL...

{
// which is never called...
}
...

Test Code  ...//Main function
{

//Construct Passive instance then cal..
passiveconn->open

//construct Active instance then call..

ActiveConn->Open //issuing connect request here

//NOW after this i start ActiveScheduler

}



   


Wed, 2003-09-17 14:40
Joined: 2003-05-27
Forum posts: 363
prob with active objects .. for TCP sockets ..
Hi,

Looking at the code, your active objects are not implemented properly - see the Symbian Programming books for more information on this.

At least the RunL methods and the Test Code look like they are causing the problems.

Cheers,
Pawel
Wed, 2003-09-17 16:12
Joined: 2003-09-17
Forum posts: 4
prob with active objects .. for TCP sockets ..
Thanks Pawel,

i'll confirm My implementation again ..
..but cud u please just review these steps  which i am trying to achieve .. and let me know if there is something fundamentally wrong in these steps .


1)I construct one active object (say A)  add it to scheduler and Issue request for Listening on this  Active object. calls SetActive()  for this Active Object

2)Construct another active object (say B) add it to Scheduler and issue request for  Connect  on this  object . Call SetActive

3) Now I start Active Scheduler .At this point i Feel two request are oustanding  and expects active sheculer to schedule the RunL metthods of both the objects (CAN I DO this??)

4) The execution reaches my RunL  of active object A  , with iStatus as KerrNone , then in this RunL I just Call  Accept method  Synchronously , which completes immiediately . and Runl Returns ..

5) Now i expect Runl of Active object B should be called BUT i Does NOT get called ..

Do you think something is wrong in implementing this ?? and it should be achievable ..

Puneet
Thu, 2003-09-18 11:45
Joined: 2003-09-05
Forum posts: 3
prob with active objects .. for TCP sockets ..
Try giving the Active object a priority of EPriorityIdle and then try.
Fri, 2003-09-19 13:55
Joined: 2003-07-25
Forum posts: 31
prob with active objects .. for TCP sockets ..
I'm still not very good at this, since I'm also trying to use it myself in my thesis...

But you did not seem to have issued a request for your passive active object. According to my experiences (basic trial and error, and struggling to understand the documentation), you need to issue a request in a function (which is not the RunL() function), in order for RunL() to be executed.

Hence what I usually do is to have a Start() function...

void Start()
{
 some_request(..., iStatus);
 SetActive();
}

and then, RunL() will be executed without any trouble...
Tue, 2003-09-23 07:23
Joined: 2003-09-17
Forum posts: 4
prob with active objects .. for TCP sockets ..
Hi ,
Actually I am issuing the request in Passive::open  function and Active Open function .. which is Listen() ... and  Connect Resp ..  and infact Runl of Pasive is  executed . the Runl of Active is not getting executed .. or you can say . with issuing two request .. only one of the RunL  gets executed ..

I tried even with changing priority to idle also..

Quote from: mjx
I'm still not very good at this, since I'm also trying to use it myself in my thesis...

But you did not seem to have issued a request for your passive active object. According to my experiences (basic trial and error, and struggling to understand the documentation), you need to issue a request in a function (which is not the RunL() function), in order for RunL() to be executed.

Hence what I usually do is to have a Start() function...

void Start()
{
  some_request(..., iStatus);
  SetActive();
}

and then, RunL() will be executed without any trouble...
Wed, 2003-10-01 10:25
Forum Nokia Champion
Joined: 2003-10-01
Forum posts: 723
You should better understand AOs
Hi,

There are few things you misunderstood.

First, RSocket::Listen is not an asynchronous call. Thus, it's meaningless to call SetActive right after invoking Listen. This method is a synchronous one and as such you can simply continue your code with preparing for a call to RSocket::Accept.

Second, you might ask : if Listen is not an asynchronous call, then why its RunL is called? Well, I have two remarks on this :
- you do not have to call an asynchronous service in order to get your RunL called by the AS (active scheduler). You simply have to assign KRequestPending to your iStatus and call SetActive and after that your RunL will be called some time.
- I realized that you did not change your request status, thus your RunL should not have been called at all. It is surprising to me, I can't help on this.

Third, do not forget that calling User::WaitForRequest should not be the preferred solution as it blocks the whole thread.

Fourth, you did not mention whether your active socket's (i.e. that wants to connect to another socket) Open method leaves or not. It might be questionable, because if your iSession member is the same RSocketServ object (is it an RSocketServ at all?) that is used by the other sockets, then calling RSocketServ::Connect the second time will result in a failure. Thus, your active socket's Open will leave as you issued a User::LeaveIfError.

Finally, If I were you I'd implement this as follows :

Code:
Passive AO::OpenL()
   {
   // prepare listening socket
   // ...
   iListeningSocket.Listen(1);

   // preparing blank socket
   // ...
   iBlankSocket.Open(...);

   // now issue the real asynchronous request
   iListeningSocket->Accept( iBlankSocket, iStatus );
   SetActive();
   }

Passive AO::RunL()
   {
   if ( iStatus.Int() == KErrNone )
       {
       RDebug::Print( _L( "Hail" ) );
       }
   else
       {
       RDebug::Print( _L( "Damn" ) );
       }
   }

Active AO::OpenL()
   {
   // Prepare the socket for connection establishment
   // ...
   iActiveSocket.Connect(...);
   SetActive();
   }

Active AO::RunL()
   {
   if ( iStatus.Int() == KErrNone )
       {
       // Change internal state, notice that the connection is established,
       // do whatever you want
       }
   else
       {
       RDebug::Print( _L( "Damn" ) );
       }
   }

Hope it helps,

tOtE

Gabor Torok
Software architect, Agil Eight (http://www.agileight.com/)
Blog: http://mobile-thoughts.blogspot.com/

Wed, 2003-10-01 12:24
Joined: 2003-09-17
Forum posts: 4
Re: You should better understand AOs
Hi Tote,

this was very helpfull for me to understand some concepts which i misunderstood, ..but in general I have some comments  
>the reason for me using ACCEPT call in side Runl was  I expect multiple  active clients may request this passive clients for  connection . For which i understand we will need to call accept again with new blank socket  and listen should not be called again . But i had a feel  there is something wrong in this . can you tell what could be better way of handling  multiple connection requests to same server.  I am not sure If we can reuse same blank socket again , after storing the handle maried to this blank socket in some other socket ( does this make sense???) ...

Also i have  one more question with Active Scheduler. It is stated in  system docs ..
""At least one active object, with an outstanding request, must be added to the scheduler before the wait loop is started, otherwise no events will occur and the thread will hang or any events that do occur will be counted as stray signals, raising a panic. """

Why this requirement ?? .. and  does that mean  in whole life of active scheduler there should be always atleast one outstanding request pending ??

thanks
Puneet
Quote from: tote
Hi,

There are few things you misunderstood.

First, RSocket::Listen is not an asynchronous call. Thus, it's meaningless to call SetActive right after invoking Listen. This method is a synchronous one and as such you can simply continue your code with preparing for a call to RSocket::Accept.

Second, you might ask : if Listen is not an asynchronous call, then why its RunL is called? Well, I have two remarks on this :
- you do not have to call an asynchronous service in order to get your RunL called by the AS (active scheduler). You simply have to assign KRequestPending to your iStatus and call SetActive and after that your RunL will be called some time.
- I realized that you did not change your request status, thus your RunL should not have been called at all. It is surprising to me, I can't help on this.

Third, do not forget that calling User::WaitForRequest should not be the preferred solution as it blocks the whole thread.

Fourth, you did not mention whether your active socket's (i.e. that wants to connect to another socket) Open method leaves or not. It might be questionable, because if your iSession member is the same RSocketServ object (is it an RSocketServ at all?) that is used by the other sockets, then calling RSocketServ::Connect the second time will result in a failure. Thus, your active socket's Open will leave as you issued a User::LeaveIfError.

Finally, If I were you I'd implement this as follows :

Code:
Passive AO::OpenL()
   {
   // prepare listening socket
   // ...
   iListeningSocket.Listen(1);

   // preparing blank socket
   // ...
   iBlankSocket.Open(...);

   // now issue the real asynchronous request
   iListeningSocket->Accept( iBlankSocket, iStatus );
   SetActive();
   }

Passive AO::RunL()
   {
   if ( iStatus.Int() == KErrNone )
       {
       RDebug::Print( _L( "Hail" ) );
       }
   else
       {
       RDebug::Print( _L( "Damn" ) );
       }
   }

Active AO::OpenL()
   {
   // Prepare the socket for connection establishment
   // ...
   iActiveSocket.Connect(...);
   SetActive();
   }

Active AO::RunL()
   {
   if ( iStatus.Int() == KErrNone )
       {
       // Change internal state, notice that the connection is established,
       // do whatever you want
       }
   else
       {
       RDebug::Print( _L( "Damn" ) );
       }
   }

Hope it helps,

tOtE
Wed, 2003-10-01 14:51
Forum Nokia Champion
Joined: 2003-10-01
Forum posts: 723
prob with active objects .. for TCP sockets ..
Hi,

I think it is still enough to use
Code:
iListeningSocket->Listen(1);
that is, 1 is enough. It specifies the number of spare slots for incoming connections. The slot becomes spare again as soon as RSocket::Accept completes, I guess.

Blank sockets : well, I have not done things like that earlier, but my opinion is as follows. You use a blank socket, because you do not know the characteristics of a remote socket in advance. When the two sockets (i.e. local and remote) are coupled, your local (and hitherto blank) socket is configured by the remote socket. After the connection is set up, it is no more a blank socket. Thus, in order to make it possible to listen (and accept) to new incoming connection requests, you have to create another blank socket and pass it to iListeningSocket's Accept method.

Example : you are a server, peering for incoming connections and maintaining current connections simultaneously. Assume that there are three established connections. What is the situation with sockets?
1 listening socket, it is pending (RSocket::Accept has not yet completed),
1 blank socket, it is passed to the listening socket,
3 properly configured sockets that are the local end-points of the connections currently "running".

Finally, AS : well, I do not fully understand the mechanism of it either, but after reading the documentation (and as I've got a few years experience) I think it is done as follows.
The AS is interested in various events, thus it issues a User::WaitForAnyRequest. This request blocks the thread (I'm not sure about this, however), so nothing can be done meanwhile, only if an AO is completed. Don't forget that the program execution is nothing else, but running AOs' RunL method, one after the other. If something happens in your program, it will always be in an AO's RunL. Thus, the AS's User::WaitForAnyRequest completes only when an AO's state changes. If there are no AOs in the AS's queue, then it will never be possible to add a new (i.e. the very first) AO as the whole thread is blocked. If User::WaitForAnyRequest happened to complete, but there is no appropriate AO in the AS's queue, then a stray signal occurs, which results in a panic in the current thread.

That's all!

tOtE

Gabor Torok
Software architect, Agil Eight (http://www.agileight.com/)
Blog: http://mobile-thoughts.blogspot.com/

Fri, 2004-01-23 18:18
Anonymous (not verified)
Forum posts: 2018
prob with active objects .. for TCP sockets ..
I have a similar problem: I have 2 apps (one server and one cliente) running on 2 emulator windows... Everything goes fine until the server accepts the connection, then both apps freeze and never call RunL...
I tried change the priority and did not work.....
Any suggestions???
That´s the code:

SERVER:

......

void CBlal::StartTestL()
     {
   StartConnection();   
   SetActive();
     }

void CBlal::StartConnection(){
   TInt err;
   TInetAddr httpPort(KInetAddrLoop, 80);

   err=ss.Connect();
   User::LeaveIfError(err);

   err = iSocket.Open(ss, KAfInet, KSockStream, KUndefinedProtocol);
   User::LeaveIfError(err);
   err = iConnection.Open(ss);
   User::LeaveIfError(err);

   err = iSocket.Bind(httpPort);
   
   iSocket.Listen(1);
   
   iSocket.Accept(iConnection, iStatus);
   User::WaitForAnyRequest();
   iChannelState = EChannelListening;
   if (iStatus == KErrNone){
        console->Printf(_L("Ouvindo conexão aceita \n"));
   }
   else{
      console->Printf(_L("Problems \n"));
      console->Printf(_L("Error:  %d\n"),iStatus);
   }
}
......

CLIENT:

......

void CModel::StartTestL()
{
   TInt err;
   TInetAddr localLoop(KInetAddrLoop, 80);
   
   RSocketServ ss;
   err=ss.Connect();
   User::LeaveIfError(err);
   
   console->Printf(_L("CREATING socket TCP...\n"));
   err = iSocket.Open(ss, KAfInet, KSockStream, KUndefinedProtocol);
   User::LeaveIfError(err);
   
   console->Printf(_L("Connecting....."));
   iSocket.Connect(localLoop, iStatus);   
   User::WaitForAnyRequest();
   console->Printf(_L("OK!\n"));
   iChannelState=EChannelSending;
   SetActive();
}


none of the two RunL functions are called after SetActive!!!!!!  Why?Huh??
  • Login to reply to this topic.