Author Topic: SW Hang due to many connection aborts ---- I suspect my TCP listner code...  (Read 16942 times)

Offline er.saurabh19

  • Newbie
  • *
  • Posts: 1
    • View Profile
Dear Mark and all other uTasker users...

I am facing a strange problem... I am observing many TCP connection aborts...
when connecting my device with PC TCP client.

My totology is as below...

                                         PC Client (TCP... Port 502)
                                              |
                                              |
       -----------------------------------------------------------------
       |                           |                                                  |
   Device no 1         Device no 2                                Device no n

All devices have the same firmware which have TCP listener on their port 502 (modbus)

What I observed some devices (not all)... hangs after some time... and when I check log
it shows several conenction aborts.. while others who still works dont shows the connection
aborts.

TCP session is as below at PC side:
PC TCP client connects to X device (make TCP Connection) ... take data in close the connection.
and again come to the device after some 3-8 seconds to take new data....


Now I suspect my TCP listner code... which we referred from HTTP listener code from
uTasker's HTTP module.....

May some corrections are needed ... please guide me

Listener code as below..........

 


/************************************************************************
TCP listener (Max socket created is 3, from the pool).. same declared... in max user socket
macro..

*************************************************************************/

static int fnTestListener(USOCKET Socket, unsigned char ucEvent, unsigned char *ucIp_Data, unsigned short usPortLen)
{
   int n,i,Ret=0;
   unsigned char TP[30];
   TCP_MESSAGE test_message;

    switch (ucEvent)
   {
   case TCP_EVENT_CONREQ:
      if(ucEvent==TCP_EVENT_CONREQ)
         {
            fnDebugMsg("\r\n---> Req for Conn..");                  // debugging info
            sprintf(TP,"[SockID=%d ] ###",Socket);
            fnDebugMsg(TP);
            ConReq++;
         }

   case TCP_EVENT_CONNECTED:
      if(ucEvent==TCP_EVENT_CONNECTED)
         {
            fnDebugMsg("\r\n---> Socket Connected..");             // debugging info
            sprintf(TP,"[SockID=%d] ###",Socket);
            fnDebugMsg(TP);
            TotCon++;
            Con++;
         }

   case TCP_EVENT_ACK:
      sprintf(TP,"[ucEvent=%d] ###",ucEvent);                    // debugging info
      fnDebugMsg(TP);

            EveAck++;
      break;

   case TCP_EVENT_ARP_RESOLUTION_FAILED:
      sprintf(TP,"[ucEvent=%d] ###",ucEvent);
      fnDebugMsg(TP);
            ARP_Fail++;  
      break;
   case TCP_EVENT_PARTIAL_ACK:
            Ret=1;
            Par_Ack++;
            fnDebugMsg("\r\n->Pack");
            sprintf(TP,"[SID=%d]##",Socket);                  // debugging info
            fnDebugMsg(TP);
            //return HANDLING_PARTICAL_ACK;
            return APP_REQUEST_CLOSE;                        //  This is also suspected !!
        break;

   case TCP_EVENT_REGENERATE:
            Regn++;
            Ret=2;
            
            if(ucEvent==TCP_EVENT_REGENERATE)
            {
               fnDebugMsg("\r\n--->REGEN");
               sprintf(TP,"[SID=%d]##",Socket);
               fnDebugMsg(TP);
            }
        

            return APP_SENT_DATA;     // May this is workaround , and suspected... !!

      break;
   case TCP_EVENT_DATA:
         Rec++;
//      sprintf(TP,"[ucEvent=%d] ###",ucEvent);
//      fnDebugMsg(TP);

         if((MenuFlag==0))
            {  
              
            TCP_ON=1;                                 //Notify Firmware that TCP meg arrive , and in process
            DecodeMsg(ucIp_Data);             // Decode msg arrived for validity
            fnDebugMsg("\nucIp_Data =");  
            for(i=0;i<20;i++)                         // Disply Msg
            {
               sprintf(TPgu,"[%u = %x]",i,ucIp_Data);
               fnDebugMsg(TPgu);
            }
            fnDebugMsg("\n");
             if(ValidFrame==1)                  // Reply Data only if modbus query is valid
                   {                                            
                        for(i=0;i<TCPd.ResponceLength;i++)
                        {
                           if(i<300)                   // Copy Modbus reply data in ti ucTCP msg buffer
                           {
                              test_message.ucTCP_Message=TCPd.RS;

                           }
                        }
                                 // Send Data                
                         if(fnSendTCP(Socket, (unsigned char *)&test_message.tTCP_Header, TCPd.ResponceLength, TCP_FLAG_PUSH) > 0)
                        {
                               return APP_SENT_DATA;
                           }
                        
                  }
                  else
                  {
                     fnDebugMsg("\n@ Not valid Frame..@");
                     //return APP_SENT_DATA;                                   // May this is not correct
                  }
                  TCP_ON=0;
            }
            else
            {
               //return APP_SENT_DATA;                                          // May this is not correct
            }
           break;

   case TCP_EVENT_ABORT:
        if(ucEvent==TCP_EVENT_ABORT)
        {
           TotAbort++;
         Con--;
           fnDebugMsg("\r\n---> Aborted..");                // debugging info
          sprintf(TP,"[SockID=%d] ###",Socket);
         fnDebugMsg(TP);
        }
   case TCP_EVENT_CLOSED:
        
      
     if(ucEvent==TCP_EVENT_CLOSED)
      {  
         TotClose++;
         Con--;
         fnDebugMsg("\r\n---> CLOSED..");                              // debugging info
         sprintf(TP,"[SockID=%d] ###",Socket);
         fnDebugMsg(TP);
      }

      
      fnTCP_Listen(Socket, usTestPort, 0);       // go back to listening state on next port number        
                                                                       // I dont know weather this is correct ... and
                                                                      // not leading to many partial opened connections
       break;
    }
   return APP_ACCEPT;                  // This is also suspected !!! why I return this as default
}    ???
« Last Edit: February 12, 2010, 02:06:46 PM by er.saurabh19 »

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3243
    • View Profile
    • uTasker
Hi

Looking at the listener I have following comments:

1) It is correct to generally return APP_ACCEPT. In any other cases a different return can be specifically returned.

2) The event TCP_EVENT_ACK is generally used as a signal to allow further data to be sent - no data should be sent before an ack to previous data has been received since this will cause TCP counter errors to occur - this can lead to the failure of a connection. This is true for simple, non-buffered TCP sockets, whereby these are very suitable for MODBUS/TCP use since there is never more than one outstanding MODBUS queries at a time.

3) TCP_EVENT_ARP_RESOLUTION_FAILED is usually handled in the same way as TCP_EVENT_REGENERATE and in TCP_EVENT_REGENERATE it is normal to repeat the last TCP frame (which must also be saved until it has been acked). It is not allowed to return  APP_SENT_DATA when no data has really been sent otherwise the TCP layer will not acknowledge data reception and so the link will fail.

4) TCP_EVENT_PARTIAL_ACK will never occur when working with a simple TCP socket - if it does it means that data is being sent without waiting for a previous frame to be acked.

5) Returning APP_REQUEST_CLOSE will cause the connection to be closed - only return it when you want this to happen.

6)

                         if(fnSendTCP(Socket, (unsigned char *)&test_message.tTCP_Header, TCPd.ResponceLength, TCP_FLAG_PUSH) > 0)
                        {
                               return APP_SENT_DATA;
                           }

This is correct use. The APP_SENT_DATA should never be returned in any other case though.

7)
fnTCP_Listen(Socket, usTestPort, 0);

This is used by a server after a connection is closed to set the server back to listening state. It is correct in the case of a server.

Regards

Mark


Further notes:

- There is also a uTasker MODBUS package which may be suitable for a project requiring MODBUS support:  http://www.utasker.com/modbus.html

- The use of TCP also also explained in the the following thread: http://www.utasker.com/forum/index.php?topic=25.0

- More details to individual TCP calls can be found in the TCP.c section of the code documentation: http://www.utasker.com/docs/Code.html


Offline aaronlawrence

  • Jr. Member
  • **
  • Posts: 66
    • View Profile
Just a wild guess, are you sure your MAC addresses are unique? I had some peculiar problems when I forget to program separate MAC addresses :)