This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C129ENCPDT: how to send data from client to server over ethernet without opening new connection/(same socket)

Part Number: TM4C129ENCPDT

Hello All,

I want to send 792 byte data from my client gateway to the server over ethernet. Now I am able to send all data over ethernet but everytime I open new connection. you can see the conenction inside yellow circle.  But I want to send all data over ethernet without opening new connection. I mean ı want only one connection in the yellow circle.

you can see the code below.

How can I configure this code to do for one connection? please let me know if you have an idea.

void ETH_Connection_Proccess(void)
{
    if(Gateway.ETHERNET_Mode == 0)
    {
        usb_printf("\n",1);
        usb_printf("ETH NOT ENABLED CAN'T POST MESSAGE\n", 35);
        Gateway.Priority = Gateway.ETHERNET_Priority + 1;
    }
    else if(ETH_Ctrl.eth_connection_status == 0)
    {
        usb_printf("\n",1);
        usb_printf("ETH NOT CONNECTED CAN'T POST MESSAGE\n", 37);
        Gateway.Priority = Gateway.ETHERNET_Priority + 1;
    }
    else if(ETH_Ctrl.eth_connection_status == 1 && Gateway.ETHERNET_Mode == 1)
    {
        ETH_Ctrl.connectTYPE = ETHERNET_POST;

        //
        //  Connect to host address
        //

        tcp_echoclient_connect(Gateway.Host_Address,Gateway.Remote_Port_Number);

        ETH_Ctrl.status = ETH_POST_CONNECT_SENT;
        ETH_Ctrl.timeout = 1;
    }
}

/**
 * @brief  Connects to the TCP echo server
 * @param  None
 * @retval None
 */
void tcp_echoclient_connect(char* IP_ARR,char* PORT_NUM)
{
    ip_addr_t DestIPaddr;

    uint16_t DestPORTAddr;

    /* create new tcp pcb */
    echoclient_pcb = tcp_new();

    if (echoclient_pcb != NULL)
    {
        ipaddr_aton((const char *)IP_ARR,&DestIPaddr);

        DestPORTAddr = atoi(PORT_NUM);

        /* connect to destination address/port */
        tcp_connect(echoclient_pcb,&DestIPaddr,DestPORTAddr,tcp_echoclient_connected);
    }
}

/**
 * @brief Function called when TCP connection established
 * @param tpcb: pointer on the connection contol block
 * @param err: when connection correctly established err should be ERR_OK
 * @retval err_t: returned error
 */
static err_t tcp_echoclient_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
{
    struct echoclient *es = NULL;
//    uint16_t index2;
    uint16_t data_lenght;
    data_lenght=792;
    if (err == ERR_OK)
    {
        /* allocate structure es to maintain tcp connection informations */
        es = (struct echoclient *)mem_malloc(sizeof(struct echoclient));

        if (es != NULL)
        {
            es->state = ES_CONNECTED;
            es->pcb = tpcb;

            if(ETH_Ctrl.connectTYPE == ETHERNET_POST)
            {
                // sprintf((char*)data,"%sContent-Length: %d\r\n\r\n%s\r\n",Gateway.POST_message_constant_part,Gateway.tcp_message_length,Gateway.tcp_message);
                 memcpy(data,Gateway.tcp_message,Gateway.tcp_message_length); //1024 tcp message datanın ilk 792 adet datası databuffer içine kaydedilir

                /* allocate pbuf */
                es->p_tx = pbuf_alloc(PBUF_TRANSPORT, sizeof(data) , PBUF_POOL); //burası gönderilen buffer ile aynı ozellikte bos bir buffer yaratıyor

                if (es->p_tx)
                {
                    /* copy data to pbuf */
//                    pbuf_take(es->p_tx, (char*)data, strlen((char*)data));
                    pbuf_take(es->p_tx, (char*)data, data_lenght); //792 byte burada yukarıda yeni tanımlananan buffera, data bufferını kopyalıyoruz

                    /* pass newly allocated es structure as argument to tpcb */
                    tcp_arg(tpcb, es);

                    /* initialize LwIP tcp_recv callback function */
                    tcp_recv(tpcb, tcp_echoclient_recv);

                    /* initialize LwIP tcp_sent callback function */
                    tcp_sent(tpcb, tcp_echoclient_sent);

                    /* initialize LwIP tcp_poll callback function */
                    tcp_poll(tpcb, tcp_echoclient_poll, 1);

                    /* send data */
                    tcp_echoclient_send(tpcb,es);

                    return ERR_OK;
                }
            }
        }
        else
        {
            /* close connection */
            tcp_echoclient_connection_close(tpcb, es);

            /* return memory allocation error */
            return ERR_MEM;
        }
    }
    else
    {
        /* close connection */
        tcp_echoclient_connection_close(tpcb, es);
    }
    return err;
}

thank you

BR,

Bekir

  • Hi,

      How do you know the connection is closed? Can you confirm with wireshark capture? Do you know if the connection is closed by the server or by the client? In your code, you will close connection when err != OK or when es == NULL. I will suggest you single step or put a breakpoint in your code if it is the client who closes the connection due to some errors. 

  • Hi thank you for your answer. I dont use wireshark. I am not sure which one close the connection, But I guess it depends on client. Because my device is client. I am programming my device according to the client. I use debugging to see what is going on. to do that  I check (pcb->state) which shows state as you can see the below.

    I check the state of (pcb->state) on debugging mode, while send data, it shows syn_sent when data transmitted, it also shows CLOSED when connection closed. 

  • Hi,

      Do you see the same connection issue if you run the client example in this app note  https://www.ti.com/lit/pdf/spna248?

      I'm not sure where your code from. It is very similar to example by STMicroelectronics. If this is the case, please read their license agreement 

    http://www.st.com/software_license_agreement_liberty_v2 and see if you are in compliance for conditions #4 and #2. I cannot support you on this. I will suggest you contact LwIP forum for support. 

    /**
      ******************************************************************************
      * @file    tcp_echoclient.c
      * @author  MCD Application Team
      * @version V1.1.0
      * @date    31-July-2013 
      * @brief   tcp echoclient application using LwIP RAW API
      ******************************************************************************
      * @attention
      *
      * <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>
      *
      * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
      * You may not use this file except in compliance with the License.
      * You may obtain a copy of the License at:
      *
      *        http://www.st.com/software_license_agreement_liberty_v2
      *
      * Unless required by applicable law or agreed to in writing, software 
      * distributed under the License is distributed on an "AS IS" BASIS, 
      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      * See the License for the specific language governing permissions and
      * limitations under the License.
      *
      ******************************************************************************
      */
    
    /* Includes ------------------------------------------------------------------*/
    #include "lwip/debug.h"
    #include "lwip/stats.h"
    #include "lwip/tcp.h"
    #include "main.h"
    #include "memp.h"
    #include "main.h"
    #include <stdio.h>
    #include <string.h>
    
    #if LWIP_TCP
    /* Private typedef -----------------------------------------------------------*/
    /* Private define ------------------------------------------------------------*/
    /* Private macro -------------------------------------------------------------*/
    /* Private variables ---------------------------------------------------------*/
    
    u8_t  recev_buf[50];
    __IO uint32_t message_count=0;
    
    u8_t   data[100];
    
    struct tcp_pcb *echoclient_pcb;
    
    
    /* ECHO protocol states */
    enum echoclient_states
    {
      ES_NOT_CONNECTED = 0,
      ES_CONNECTED,
      ES_RECEIVED,
      ES_CLOSING,
    };
    
    
    /* structure to be passed as argument to the tcp callbacks */
    struct echoclient
    {
      enum echoclient_states state; /* connection status */
      struct tcp_pcb *pcb;          /* pointer on the current tcp_pcb */
      struct pbuf *p_tx;            /* pointer on pbuf to be transmitted */
    };
    
    
    /* Private function prototypes -----------------------------------------------*/
    static err_t tcp_echoclient_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
    static void tcp_echoclient_connection_close(struct tcp_pcb *tpcb, struct echoclient * es);
    static err_t tcp_echoclient_poll(void *arg, struct tcp_pcb *tpcb);
    static err_t tcp_echoclient_sent(void *arg, struct tcp_pcb *tpcb, u16_t len);
    static void tcp_echoclient_send(struct tcp_pcb *tpcb, struct echoclient * es);
    static err_t tcp_echoclient_connected(void *arg, struct tcp_pcb *tpcb, err_t err);
    
    /* Private functions ---------------------------------------------------------*/
    
    
    /**
    * @brief  Connects to the TCP echo server
    * @param  None
    * @retval None
    */
    void tcp_echoclient_connect(void)
    {
      struct ip_addr DestIPaddr;
      
      /* create new tcp pcb */
      echoclient_pcb = tcp_new();
      
      if (echoclient_pcb != NULL)
      {
        IP4_ADDR( &DestIPaddr, DEST_IP_ADDR0, DEST_IP_ADDR1, DEST_IP_ADDR2, DEST_IP_ADDR3 );
        
        /* connect to destination address/port */
        tcp_connect(echoclient_pcb,&DestIPaddr,DEST_PORT,tcp_echoclient_connected);
      }
      else
      {
        /* deallocate the pcb */
        memp_free(MEMP_TCP_PCB, echoclient_pcb);
    #ifdef SERIAL_DEBUG
        printf("\n\r can not create tcp pcb");
    #endif 
      }
    }
    
    /**
      * @brief Function called when TCP connection established
      * @param tpcb: pointer on the connection contol block
      * @param err: when connection correctly established err should be ERR_OK 
      * @retval err_t: returned error 
      */
    static err_t tcp_echoclient_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
    {
      struct echoclient *es = NULL;
      
      if (err == ERR_OK)   
      {
        /* allocate structure es to maintain tcp connection informations */
        es = (struct echoclient *)mem_malloc(sizeof(struct echoclient));
      
        if (es != NULL)
        {
          es->state = ES_CONNECTED;
          es->pcb = tpcb;
          
          sprintf((char*)data, "sending tcp client message %d", message_count);
            
          /* allocate pbuf */
          es->p_tx = pbuf_alloc(PBUF_TRANSPORT, strlen((char*)data) , PBUF_POOL);
             
          if (es->p_tx)
          {       
            /* copy data to pbuf */
            pbuf_take(es->p_tx, (char*)data, strlen((char*)data));
            
            /* pass newly allocated es structure as argument to tpcb */
            tcp_arg(tpcb, es);
      
            /* initialize LwIP tcp_recv callback function */ 
            tcp_recv(tpcb, tcp_echoclient_recv);
      
            /* initialize LwIP tcp_sent callback function */
            tcp_sent(tpcb, tcp_echoclient_sent);
      
            /* initialize LwIP tcp_poll callback function */
            tcp_poll(tpcb, tcp_echoclient_poll, 1);
        
            /* send data */
            tcp_echoclient_send(tpcb,es);
            
            return ERR_OK;
          }
        }
        else
        {
          /* close connection */
          tcp_echoclient_connection_close(tpcb, es);
          
          /* return memory allocation error */
          return ERR_MEM;  
        }
      }
      else
      {
        /* close connection */
        tcp_echoclient_connection_close(tpcb, es);
      }
      return err;
    }

  • Hi,

    There is no same issue in the app note. I dont compliance for conditions #2 and #4. I found a solution which is working but I am not sure that is true or not.

    In the beginning the code enters in the eth_repeat_2 state. it gets connections and then never goes into the this state. After get the tpcbSa socket from the first state, I use this socket for tcp_echoserver_send2 func to send data continuously. Do you think it is correct.

    void ETH_Connection_Proccess(void)
    {
        if(Gateway.ETHERNET_Mode == 0)
        {
            usb_printf("\n",1);
            usb_printf("ETH NOT ENABLED CAN'T POST MESSAGE\n", 35);
            Gateway.Priority = Gateway.ETHERNET_Priority + 1;
        }
        else if(ETH_Ctrl.eth_connection_status == 0)
        {
            usb_printf("\n",1);
            usb_printf("ETH NOT CONNECTED CAN'T POST MESSAGE\n", 37);
            Gateway.Priority = Gateway.ETHERNET_Priority + 1;
        }
        else if(ETH_Ctrl.eth_connection_status == 1 && Gateway.ETHERNET_Mode == 1)
        {
            ETH_Ctrl.connectTYPE = ETHERNET_POST;
    
            //
            //  Connect to host address
            //
            if(ETH_Ctrl.eth_data_repeat == ETH_REPEAT_2)
            {
                tcp_echoclient_connect(Gateway.Host_Address,Gateway.Remote_Port_Number);
            }
            else if(ETH_Ctrl.eth_data_repeat == ETH_REPEAT_1)
            {
                memcpy(data,Gateway.tcp_message,Gateway.tcp_message_length);
                tcp_echoserver_send2(tpcbSa, (unsigned char*)data, sizeof(data));
    
                if(ETH_Ctrl.connectTYPE == ETHERNET_POST)               //if post request and we want to close connection
                {
                    ETH_Ctrl.status = ETH_STATUS_POSTED;            //indicate that we post message successfully
                }
                else {
    
                    ETH_Ctrl.status = ETH_POST_CONNECT_SENT;
                    ETH_Ctrl.timeout = 1;
                }
            }
    }
    .
    void tcp_echoserver_send2(struct tcp_pcb *tpcb, unsigned char *Source, unsigned int Size)
    {
        err_t wr_err = ERR_OK;
    
        /* enqueue data for transmission */
        wr_err = tcp_write(tpcb, Source, Size, 1);
    
        if(wr_err == ERR_OK)
            wr_err = tcp_output(tpcb);
    
    }

  • Hi,

      You didn't show when ETH_Ctrl.eth_data_repeat becomes ETH_REPEAT_2 or ETH_REPEAT_1 and how the ETH_Connection_Proccess() is called. I think if you make sure you only call tcp_echoclient_connect once and as you have proven it is working, then I think it should be fine. 

  • Hİ,

    I am sorry I forget where I put. ETH_Ctrl.eth_data_repeat becomes ETH_REPEAT_1 in the tcp_client_connect function. thus it will be only one connection as you said. after that it only works  tcp_echoserver_send2 functions which send all datas. this way is working very well. but lets say server is closed. what is going to happen then? do I need to open new connection? I mean do I have to ETH_Ctrl.eth_data_repeat become ETH_REPEAT_2 that able to do new connection? 

    void tcp_echoclient_connect(char* IP_ARR,char* PORT_NUM)
    {
        {
            /* create new tcp pcb */
            echoclient_pcb = tcp_new();
            if (echoclient_pcb != NULL)// || ETH_Ctrl.eth_data_repeat == ETH_REPEAT_2)
            {
                ETH_Ctrl.eth_data_repeat = ETH_REPEAT_1;
                ipaddr_aton((const char *)IP_ARR,&DestIPaddr);
                DestPORTAddr = atoi(PORT_NUM);
    
                /* connect to destination address/port */
                tcp_connect(echoclient_pcb,&DestIPaddr,DestPORTAddr,tcp_echoclient_connected);
            }
        }
    }

    thanl you

  • Hi,

      I'm not sure about the answer to your question as I don't have enough knowledge on this topic. I guess the client could ping the server and if you get timeout then you know the server closes the connection. 

      Perhaps this below article could help you. You are asking a network-centric question that is beyond the scope of the MCU that we have enough knowledge to answer. I will suggest you do some Google searches for some opinions/ideas how to handle server closed its connection. 

    https://www.geeksforgeeks.org/tcp-connection-termination/