2024-05-06 01:45 AM - last edited on 2024-05-20 08:00 AM by Aziz BRIGUI
HI team,
I am Using NUCLEO-F439ZI board for Ethernet Interface. I successfully transferred the data in UDP, Now I try to send the data using TCP client method.
In the .ioc configuration file, I followed the below setup
1. Connectivity -> ETH -> RMII mode.
2. Middleware and Software Packs -> LWIP -> General Setting -> LWIP_DHCP (set own IP -> 192.168.1.10)
Middleware and Software Packs -> LWIP -> Key Option -> heap memory size = 10*1024 bytes.
Middleware and Software Packs -> LWIP -> HTTPD -> LWIP_HTTPD - enable
after all this setup I generate the code
In the Main.c file
1. by using this code I ping the connection, its works fine "extern struct netif gnetif;
ethernetif_input(&gnetif);
sys_check_timeouts();".
2. from this sub function "tcp_server_init();",
To create a TCP block,
Bind the socket to Server Address
Listen from client
Accept function - connection between client and server
After done all this process it successfully debugs and make the connection successfully
The connection made successfully, whenever I try to send the data, the following error
occurred. The below attachment shows the error.
In the "static void tcp_server_handle (struct tcp_pcb *tpcb, struct tcp_server_struct *es)" function I changed the code this code " char buf[100]; memset (buf, '\0', 100); strncpy(buf, (char *)es->p->payload, es->p->tot_len);
The detailed "tcp_server_init()" program was attached below for your reference
Thank you
regards
RAMACHANDRAN.S
Solved! Go to Solution.
2024-05-31 06:02 AM
Hello @Ramachandran1992 ,
After an examination of the attached file, it seems tcp_server_handle you are implementing is unable to properly allocate a buffer this should be done with the Pbuf_alloc function.
my recommendation is to take the example we give in the cube Firmware which can be obtained from Github or from the ST website as a reference so the revised version of your tcp_server_raw.c will be as follows :
/**
******************************************************************************
* @file LwIP/LwIP_TCP_Echo_Client/Src/tcp_echoclient.c
* @author MCD Application Team
* @brief tcp echoclient application using LwIP RAW API
******************************************************************************
* @attention
*
* Copyright (c) 2017 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/tcp.h"
#include "lwip/memp.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)
{
ip_addr_t 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);
}
}
/**
* @brief Function called when TCP connection established
* @param tpcb: pointer on the connection control 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 information */
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", (int)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;
}
/**
* @brief tcp_receiv callback
* @param arg: argument to be passed to receive callback
* @param tpcb: tcp connection control block
* @param err: receive error code
* @retval err_t: returned error
*/
static err_t tcp_echoclient_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
struct echoclient *es;
err_t ret_err;
LWIP_ASSERT("arg != NULL",arg != NULL);
es = (struct echoclient *)arg;
/* if we receive an empty tcp frame from server => close connection */
if (p == NULL)
{
/* remote host closed connection */
es->state = ES_CLOSING;
if(es->p_tx == NULL)
{
/* we're done sending, close connection */
tcp_echoclient_connection_close(tpcb, es);
}
else
{
/* send remaining data*/
tcp_echoclient_send(tpcb, es);
}
ret_err = ERR_OK;
}
/* else : a non empty frame was received from echo server but for some reason err != ERR_OK */
else if(err != ERR_OK)
{
/* free received pbuf*/
if (p != NULL)
{
pbuf_free(p);
}
ret_err = err;
}
else if(es->state == ES_CONNECTED)
{
/* increment message count */
message_count++;
/* Acknowledge data reception */
tcp_recved(tpcb, p->tot_len);
pbuf_free(p);
tcp_echoclient_connection_close(tpcb, es);
ret_err = ERR_OK;
}
/* data received when connection already closed */
else
{
/* Acknowledge data reception */
tcp_recved(tpcb, p->tot_len);
/* free pbuf and do nothing */
pbuf_free(p);
ret_err = ERR_OK;
}
return ret_err;
}
/**
* @brief function used to send data
* @param tpcb: tcp control block
* @param es: pointer on structure of type echoclient containing info on data
* to be sent
* @retval None
*/
static void tcp_echoclient_send(struct tcp_pcb *tpcb, struct echoclient * es)
{
struct pbuf *ptr;
err_t wr_err = ERR_OK;
while ((wr_err == ERR_OK) &&
(es->p_tx != NULL) &&
(es->p_tx->len <= tcp_sndbuf(tpcb)))
{
/* get pointer on pbuf from es structure */
ptr = es->p_tx;
/* enqueue data for transmission */
wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1);
if (wr_err == ERR_OK)
{
/* continue with next pbuf in chain (if any) */
es->p_tx = ptr->next;
if(es->p_tx != NULL)
{
/* increment reference count for es->p */
pbuf_ref(es->p_tx);
}
/* free pbuf: will free pbufs up to es->p (because es->p has a reference count > 0) */
pbuf_free(ptr);
}
else if(wr_err == ERR_MEM)
{
/* we are low on memory, try later, defer to poll */
es->p_tx = ptr;
}
else
{
/* other problem ?? */
}
}
}
/**
* @brief This function implements the tcp_poll callback function
* @param arg: pointer on argument passed to callback
* @param tpcb: tcp connection control block
* @retval err_t: error code
*/
static err_t tcp_echoclient_poll(void *arg, struct tcp_pcb *tpcb)
{
err_t ret_err;
struct echoclient *es;
es = (struct echoclient*)arg;
if (es != NULL)
{
if (es->p_tx != NULL)
{
/* there is a remaining pbuf (chain) , try to send data */
tcp_echoclient_send(tpcb, es);
}
else
{
/* no remaining pbuf (chain) */
if(es->state == ES_CLOSING)
{
/* close tcp connection */
tcp_echoclient_connection_close(tpcb, es);
}
}
ret_err = ERR_OK;
}
else
{
/* nothing to be done */
tcp_abort(tpcb);
ret_err = ERR_ABRT;
}
return ret_err;
}
/**
* @brief This function implements the tcp_sent LwIP callback (called when ACK
* is received from remote host for sent data)
* @param arg: pointer on argument passed to callback
* @param tcp_pcb: tcp connection control block
* @param len: length of data sent
* @retval err_t: returned error code
*/
static err_t tcp_echoclient_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
{
struct echoclient *es;
LWIP_UNUSED_ARG(len);
es = (struct echoclient *)arg;
if(es->p_tx != NULL)
{
/* still got pbufs to send */
tcp_echoclient_send(tpcb, es);
}
return ERR_OK;
}
/**
* @brief This function is used to close the tcp connection with server
* @param tpcb: tcp connection control block
* @param es: pointer on echoclient structure
* @retval None
*/
static void tcp_echoclient_connection_close(struct tcp_pcb *tpcb, struct echoclient * es )
{
/* remove callbacks */
tcp_recv(tpcb, NULL);
tcp_sent(tpcb, NULL);
tcp_poll(tpcb, NULL,0);
if (es != NULL)
{
mem_free(es);
}
/* close tcp connection */
tcp_close(tpcb);
}
#endif /* LWIP_TCP */
Regards
2024-05-31 06:02 AM
Hello @Ramachandran1992 ,
After an examination of the attached file, it seems tcp_server_handle you are implementing is unable to properly allocate a buffer this should be done with the Pbuf_alloc function.
my recommendation is to take the example we give in the cube Firmware which can be obtained from Github or from the ST website as a reference so the revised version of your tcp_server_raw.c will be as follows :
/**
******************************************************************************
* @file LwIP/LwIP_TCP_Echo_Client/Src/tcp_echoclient.c
* @author MCD Application Team
* @brief tcp echoclient application using LwIP RAW API
******************************************************************************
* @attention
*
* Copyright (c) 2017 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/tcp.h"
#include "lwip/memp.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)
{
ip_addr_t 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);
}
}
/**
* @brief Function called when TCP connection established
* @param tpcb: pointer on the connection control 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 information */
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", (int)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;
}
/**
* @brief tcp_receiv callback
* @param arg: argument to be passed to receive callback
* @param tpcb: tcp connection control block
* @param err: receive error code
* @retval err_t: returned error
*/
static err_t tcp_echoclient_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
struct echoclient *es;
err_t ret_err;
LWIP_ASSERT("arg != NULL",arg != NULL);
es = (struct echoclient *)arg;
/* if we receive an empty tcp frame from server => close connection */
if (p == NULL)
{
/* remote host closed connection */
es->state = ES_CLOSING;
if(es->p_tx == NULL)
{
/* we're done sending, close connection */
tcp_echoclient_connection_close(tpcb, es);
}
else
{
/* send remaining data*/
tcp_echoclient_send(tpcb, es);
}
ret_err = ERR_OK;
}
/* else : a non empty frame was received from echo server but for some reason err != ERR_OK */
else if(err != ERR_OK)
{
/* free received pbuf*/
if (p != NULL)
{
pbuf_free(p);
}
ret_err = err;
}
else if(es->state == ES_CONNECTED)
{
/* increment message count */
message_count++;
/* Acknowledge data reception */
tcp_recved(tpcb, p->tot_len);
pbuf_free(p);
tcp_echoclient_connection_close(tpcb, es);
ret_err = ERR_OK;
}
/* data received when connection already closed */
else
{
/* Acknowledge data reception */
tcp_recved(tpcb, p->tot_len);
/* free pbuf and do nothing */
pbuf_free(p);
ret_err = ERR_OK;
}
return ret_err;
}
/**
* @brief function used to send data
* @param tpcb: tcp control block
* @param es: pointer on structure of type echoclient containing info on data
* to be sent
* @retval None
*/
static void tcp_echoclient_send(struct tcp_pcb *tpcb, struct echoclient * es)
{
struct pbuf *ptr;
err_t wr_err = ERR_OK;
while ((wr_err == ERR_OK) &&
(es->p_tx != NULL) &&
(es->p_tx->len <= tcp_sndbuf(tpcb)))
{
/* get pointer on pbuf from es structure */
ptr = es->p_tx;
/* enqueue data for transmission */
wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1);
if (wr_err == ERR_OK)
{
/* continue with next pbuf in chain (if any) */
es->p_tx = ptr->next;
if(es->p_tx != NULL)
{
/* increment reference count for es->p */
pbuf_ref(es->p_tx);
}
/* free pbuf: will free pbufs up to es->p (because es->p has a reference count > 0) */
pbuf_free(ptr);
}
else if(wr_err == ERR_MEM)
{
/* we are low on memory, try later, defer to poll */
es->p_tx = ptr;
}
else
{
/* other problem ?? */
}
}
}
/**
* @brief This function implements the tcp_poll callback function
* @param arg: pointer on argument passed to callback
* @param tpcb: tcp connection control block
* @retval err_t: error code
*/
static err_t tcp_echoclient_poll(void *arg, struct tcp_pcb *tpcb)
{
err_t ret_err;
struct echoclient *es;
es = (struct echoclient*)arg;
if (es != NULL)
{
if (es->p_tx != NULL)
{
/* there is a remaining pbuf (chain) , try to send data */
tcp_echoclient_send(tpcb, es);
}
else
{
/* no remaining pbuf (chain) */
if(es->state == ES_CLOSING)
{
/* close tcp connection */
tcp_echoclient_connection_close(tpcb, es);
}
}
ret_err = ERR_OK;
}
else
{
/* nothing to be done */
tcp_abort(tpcb);
ret_err = ERR_ABRT;
}
return ret_err;
}
/**
* @brief This function implements the tcp_sent LwIP callback (called when ACK
* is received from remote host for sent data)
* @param arg: pointer on argument passed to callback
* @param tcp_pcb: tcp connection control block
* @param len: length of data sent
* @retval err_t: returned error code
*/
static err_t tcp_echoclient_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
{
struct echoclient *es;
LWIP_UNUSED_ARG(len);
es = (struct echoclient *)arg;
if(es->p_tx != NULL)
{
/* still got pbufs to send */
tcp_echoclient_send(tpcb, es);
}
return ERR_OK;
}
/**
* @brief This function is used to close the tcp connection with server
* @param tpcb: tcp connection control block
* @param es: pointer on echoclient structure
* @retval None
*/
static void tcp_echoclient_connection_close(struct tcp_pcb *tpcb, struct echoclient * es )
{
/* remove callbacks */
tcp_recv(tpcb, NULL);
tcp_sent(tpcb, NULL);
tcp_poll(tpcb, NULL,0);
if (es != NULL)
{
mem_free(es);
}
/* close tcp connection */
tcp_close(tpcb);
}
#endif /* LWIP_TCP */
Regards