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.
/******************************************************************************
* 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;
}