Author Topic: More TCP clients  (Read 8953 times)

Offline Forrest

  • Newbie
  • *
  • Posts: 4
    • View Profile
More TCP clients
« on: December 22, 2008, 07:39:00 AM »
Hi all,

Im building application with more tcp clients i need. uTasker support up to 128 sockets. So im thinking thats no problem there. But if im dooing this code (follow bottom) and if a have more then 3 clients uTasker restarts. The application is wery easy, client sending request and if server not send response the uTasker wont to connect them, and if server send response client send new request. The requests is modbus TCP.
The variable USER_TCP_SOCKETS is set to 51, and maximum connection whitch a tests was 4.

Code: [Select]
/******************************************************************************
* Include
******************************************************************************/
#include "config.h"
#include "mb_tcp_c.h"
#include "TaskConfig.h"
#include "modbus.h"

/******************************************************************************
* Type defines
******************************************************************************/
typedef struct st_MB_TCP_MESSAGE
{
    TCP_HEADER     tTCP_Header;      // reserve header space
    unsigned char  data[MB_TCP_MAX_BUF]; // data space
   
} MB_TCP_MESSAGEE;

typedef struct st_IP_socket
{
USOCKET socket; // socket
unsigned char ip[IPV4_LENGTH]; // IP adresa
unsigned char status; // status pro komunikaci
unsigned short frame_lenght; // vypocitana delka ramce pro prijeti celeho paketu
unsigned char receive_counter; // prijimaci counter
} IP_SOCKET;

/******************************************************************************
* Global variables
******************************************************************************/
unsigned char user_buffer[MB_TCP_MAX_BUF]; // buffer pro zadavani pozadavku z LCD
unsigned short packet_counter = 0; // counter for generate unique Transaction Identifier


MB_TCP_MESSAGEE mb_tcp_c_mess; // TCP buffer pro vysilani pozadavku
IP_SOCKET ip_sockets[USER_TCP_SOCKETS]; // pole s TCP pripojenim







//-----------------------------------------------------------------------------
// Module:   fn_MB_tcp_c_listener
// Description: naslouchac pro mb clienta
//-----------------------------------------------------------------------------
static int fnMB_tcp_c_Listener(USOCKET Socket, unsigned char ucEvent, unsigned char *ucIp_Data, unsigned short usPortLen)
{

unsigned char socket;
int ret;


socket = search_socket_index(Socket);


switch(ucEvent)
{
//prijali jsme data
case TCP_EVENT_DATA: //prijali jsme data ktera navazuji na predchozi ramec

ret = fn_receive_response_header(Socket, ucIp_Data, usPortLen);

break;

//prijali jsme potvrzeni acknowledge
case TCP_EVENT_ACK:
#ifdef TCP_CLIENT_VERBOSE
fnDebugMsg("TCP_EVENT_ACK ");
fnDebugDec(ip_sockets[socket].ip[3],0,0);
fnDebugMsg(" \n\r");
#endif

ret = APP_ACCEPT;
break;

//uspesne spojeni se serverem
case TCP_EVENT_CONNECTED:
#ifdef TCP_CLIENT_VERBOSE
fnDebugMsg("TCP_EVENT_CONNECTED ");
fnDebugDec(ip_sockets[socket].ip[3],0,0);
fnDebugMsg(" \n\r");
#endif

ret = fn_mb_tcp_rr(0,20,Socket); //precteme prvni registr
break;

//pakety se ztratily -> znovu vysleme pozadavek
case TCP_EVENT_REGENERATE:
#ifdef TCP_CLIENT_VERBOSE
fnDebugMsg("TCP_EVENT_REGENERATE ");
fnDebugDec(ip_sockets[socket].ip[3],0,0);
fnDebugMsg(" \n\r");
#endif

ret = fn_mb_tcp_rr(0,20,Socket);
break;

//zacatek ukonceni spojeni nedelame nic
case TCP_EVENT_CLOSE:
#ifdef TCP_CLIENT_VERBOSE
fnDebugMsg("TCP_EVENT_CLOSE ");
fnDebugDec(ip_sockets[socket].ip[3],0,0);
fnDebugMsg(" \n\r");
#endif

ret = APP_ACCEPT;
break;

//ulpne ukonceni spojeni pokusime se spojit se serverem znovu
case TCP_EVENT_CLOSED:
#ifdef TCP_CLIENT_VERBOSE
fnDebugMsg("TCP_EVENT_CLOSED ");
fnDebugDec(ip_sockets[socket].ip[3],0,0);
fnDebugMsg(" \n\r");
#endif

connect(Socket);

ret = APP_ACCEPT;
break;

//spojeni bylo ukonceno nejaka nedefinovatelna chyba error nebo reset serveru
case TCP_EVENT_ABORT:
#ifdef TCP_CLIENT_VERBOSE
fnDebugMsg("TCP_EVENT_ABORT ");
fnDebugDec(ip_sockets[socket].ip[3],0,0);
fnDebugMsg(" \n\r");
#endif

connect(Socket);

ret = APP_ACCEPT;
break;

//generuje se pokud pracujeme jako klient a posilame data nebo ack po dlouhe dobe a
//muze se stat ze server zdechnul nebo je problem se siti nebo server proste neexistuje
//spojeni se serverem neni mozne nebo spojeni selhalo
case TCP_EVENT_ARP_RESOLUTION_FAILED:
#ifdef TCP_CLIENT_VERBOSE
fnDebugMsg("TCP_EVENT_ARP_RESOLUTION_FAILED ");
fnDebugDec(ip_sockets[socket].ip[3],0,0);
fnDebugMsg(" \n\r");
#endif

connect(Socket);

ret = APP_ACCEPT;
break;

//defaultni nastaveni
default: ret = APP_ACCEPT; break;
}

return ret;

}

//-----------------------------------------------------------------------------
// Module:   fn_receive_response_header
// Description: kontroluje odpoved serveru -> kontroluje pouze spravnost
//-----------------------------------------------------------------------------
int fn_receive_response_header(USOCKET Socket, unsigned char *ucIp_Data, unsigned short usPortLen)
{

unsigned char socket = search_socket_index(Socket);
unsigned char * data_pointer = ucIp_Data;
unsigned short frame_lenght;


if(usPortLen < MB_TCP_MBAP_HEADER_SIZE)
{
#ifdef TCP_CLIENT_VERBOSE
fnDebugMsg("SMALL MBAP TCP HEADER SIZE ");
fnDebugHex(Socket, 1);
fnDebugMsg(" \n");
#endif

return APP_ACCEPT;
}

if(data_pointer[2]!=0 || data_pointer[3]!=0)
{
#ifdef TCP_CLIENT_VERBOSE
fnDebugMsg("ILLEGAL PROTOCOL ");
fnDebugHex(Socket, 1);
fnDebugMsg(" \n");
#endif

return APP_ACCEPT;
}

//count new frame lenght
ip_sockets[socket].frame_lenght = (unsigned short)(((unsigned short) data_pointer[4] << 8) + ((unsigned short) data_pointer[5]) + 6);

if(usPortLen > ip_sockets[socket].frame_lenght)
{
#ifdef TCP_CLIENT_VERBOSE
fnDebugMsg("INVALID LENGHT - DATA TO LONG");
fnDebugHex(Socket, 1);
fnDebugMsg(" \n");
#endif

return APP_ACCEPT;
}


if((ip_sockets[socket].receive_counter+usPortLen) < ip_sockets[socket].frame_lenght)
{
#ifdef TCP_CLIENT_VERBOSE
fnDebugMsg("PIECE OF DATA RECEIVED");
fnDebugHex(Socket, 1);
fnDebugMsg(" \n");
#endif

// uMemcpy((unsigned int *)& ip_sockets[socket].buffer[0],ucIp_Data,usPortLen);
ip_sockets[socket].receive_counter += usPortLen;
ip_sockets[socket].status = RECEIVE_ALL_FRAME;

return APP_ACCEPT;
}

#ifdef PRINT_RESPONSE
fnDebugMsg("YES");
#endif

//uMemcpy((unsigned int *)& ip_sockets[socket].buffer[0],ucIp_Data,usPortLen); //copy all data
ip_sockets[socket].receive_counter = 0;
ip_sockets[socket].frame_lenght = 0;
ip_sockets[socket].status = RECEIVE_HEADER;
//tady musi byt vyhodnoceni dotazu

return fn_mb_tcp_rr(0,20,Socket); //precteme prvni registr
}

//-----------------------------------------------------------------------------
// Module:   fn_TCP_mb_c_start
// Description: init funkce pro task "MB client"
//-----------------------------------------------------------------------------
void fn_TCP_mb_c_init(TTASKTABLE *ptrTaskTable)
{
//uTaskerMonoTimer(TASK_TCP_MB_C, (0.5*SEC), 2); //zkouseni MONO timeru

unsigned char i;
unsigned char ip = 81;

//prace s konfiguracnim souborem

for(i=0; i<MAX_SOCKET; i++)
{
#ifdef PC_TCP_MB
if(i == 0)
{
ip_sockets[i].ip[0] = 192;
ip_sockets[i].ip[1] = 168;
ip_sockets[i].ip[2] = 1;
ip_sockets[i].ip[3] = 25;
}
else
{
#endif
ip_sockets[i].ip[0] = 192;
ip_sockets[i].ip[1] = 168;
ip_sockets[i].ip[2] = 1;
ip_sockets[i].ip[3] = ip;
ip++;
#ifdef PC_TCP_MB
}
#endif
ip_sockets[i].status = RECEIVE_HEADER;
ip_sockets[i].receive_counter = 0;
ip_sockets[i].frame_lenght = 0;
ip_sockets[i].socket = fnGetTCP_Socket(TOS_MINIMISE_DELAY, 10, fnMB_tcp_c_Listener);

if(ip_sockets[i].socket >= 0)
{
fnTCP_Connect(ip_sockets[i].socket,ip_sockets[i].ip, MB_TCP_PORT, 0, 0);
fnDebugMsg("Get socket for ip ");
fnDebugDec(ip_sockets[i].ip[3],0,0);
fnDebugMsg("... \n\r");
}


}
}

//-----------------------------------------------------------------------------
// Module:   connect
// Description: navaze spojeni se serverem podle ip ktere je u socketu ulozeno
//-----------------------------------------------------------------------------
signed char connect(USOCKET Socket)
{
signed char i = search_socket_index(Socket);

fnTCP_Connect(ip_sockets[i].socket,ip_sockets[i].ip, MB_TCP_PORT, 0, 0);

return 0;
}


//-----------------------------------------------------------------------------
// Module:   search_socket_index
// Description: podle predaneho socketu vrati index kde se nachazi zaznam pro
// predany socket jinak vraci -1
//-----------------------------------------------------------------------------
signed char search_socket_index(USOCKET Socket)
{
signed char i = 0;
signed char ret = 0;

while(i<MAX_SOCKET)
{
if(Socket == ip_sockets[i].socket)
{
ret = 1;
break;
}
i++;
}
if(ret) return i;
else return -1;
}

//*****************************************************************************
//*****************************************************************************
//****************************** MBUS TCP *************************************
//*****************************************************************************
//*****************************************************************************

//-----------------------------------------------------------------------------
// Module:   fn_mb_tcp_rr
// Description: modbus tcp read register funkce, vytvori dotaz na cteni registru
// predava se adresa pro cteni a pocet registru
//-----------------------------------------------------------------------------
int fn_mb_tcp_rr(unsigned int start_adres, unsigned int quantity, USOCKET Socket){

//make MB query
    mb_tcp_c_mess.data[0]= 0x03; //insert function code
    mb_tcp_c_mess.data[1]= start_adres>>8;  //start address
    mb_tcp_c_mess.data[2]=(unsigned char)(start_adres);
    mb_tcp_c_mess.data[3]= quantity>>8; //number of items
    mb_tcp_c_mess.data[4]=(unsigned char)(quantity);
         
    return add_mbap_header((unsigned char *)& mb_tcp_c_mess.data[0], 5, Socket);
}

//-----------------------------------------------------------------------------
// Module:   add_mbap_header
// Description: prida MBAP hlavicku ke zhotovenemu MB dotazu
//  jako parametr se bere ukazatel na buffer kde se prepoklada
// vytvoreny dotaz a velikost dotazu v bytech
//-----------------------------------------------------------------------------
int add_mbap_header (unsigned char *data_buffer, unsigned short data_lenght, USOCKET Socket)
{

unsigned short i = 0; //variable for rotate data
unsigned char  * dest;
unsigned char  * source;

dest = data_buffer + data_lenght + MB_TCP_MBAP_HEADER_SIZE;
source = data_buffer + data_lenght;


data_lenght += 1; //count new data_lenght

//all data rotate to right
for(i=data_lenght; i>0; i--)
{
*dest = *source;
dest--;source--;
}

//add header
*data_buffer = packet_counter >> 8; //add Transaction Identifier 2bytes
data_buffer++;
*data_buffer = (unsigned char) packet_counter;
data_buffer++;
*data_buffer = MB_TCP_PROTOCOL_IDENTIFIER >> 8; //add Protocol Identifier 2bytes for modbus TCP/IP is 0x0000
data_buffer++;
*data_buffer = (unsigned char) MB_TCP_PROTOCOL_IDENTIFIER;
data_buffer++;
*data_buffer = data_lenght >> 8; //add lenght (mb data lenght + 1 byte data identifier
data_buffer++;
*data_buffer = (unsigned char) data_lenght;
data_buffer++;
*data_buffer = MB_TCP_UNIT_IDENTIFIER; //add Unit Identifier

data_lenght += (MB_TCP_MBAP_HEADER_SIZE-1);

return send_request((unsigned char *)& mb_tcp_c_mess, data_lenght, Socket);
}

//-----------------------------------------------------------------------------
// Module:   send_request
// Description: odesle TCP dotaz
//-----------------------------------------------------------------------------
int send_request(unsigned char *data_buffer, unsigned short data_lenght, USOCKET Socket)
{
if(fnSendTCP(Socket, data_buffer, data_lenght, TCP_FLAG_PUSH)>0){
packet_counter++;
#ifdef TCP_CLIENT_VERBOSE
fnDebugMsg("Sending data... \n\r");
#endif
return APP_SENT_DATA;
}

return APP_ACCEPT;
}

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: More TCP clients
« Reply #1 on: December 22, 2008, 08:05:31 AM »
Hi

Can you identify where the problem is (eg. in which part of code and when the problem occurs? For example when a connection is started, etc.).
Also check the RAM memory usage. Is it possible that each socket requires additional memory and it fails due to this restriction?
Can you run the program in the simulator? This may help identify problems due to target memory restrictions.

Regards

Mark

Offline Forrest

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: More TCP clients
« Reply #2 on: December 22, 2008, 10:57:14 AM »
Hi Mark

Im succesful solve this problem with my colleague. The mystake was i print to much and long messages over UART.  For example if i accept data. So ethernet is more faster then uart (baud rate i use 115200).
The behaviour was if application starting, succesful get socket and connect to server and 7 or 8 second running and suddenly restart. I disable printing messages and now application communicating valid.

Regards Forrest

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: More TCP clients
« Reply #3 on: December 22, 2008, 07:22:02 PM »
Hi Forrest

Which processor are you using? It is normal that debug output will be lost when large amounts of data are sent to the UART (more than the output buffer can accept) but it shouldn,t result in a reset of the board.
When there is no more buffer space the data should simply be dropped.

Regards

Mark