2021-04-29 04:28 AM
Hi, I create a project on stm32f746 nucleo board using LWIP stack (netconn) and FreeRTOS.
The main function of this project is HTTP server. But I have a few problems with this functionality - they are errors of connection and close states of HTTP session.
Have anybody working project of HTTP server (netconn) which can make a good connection without errors, RST, retransmissions? I am needed a code of stability working server because tested a lot of codes, but all of its works not perfect.
Maybe I did a mistake in this code?
Code which I use:
typedef struct struct_sock_t {
struct netconn *conn;
} struct_sock;
struct_sock sock;
void StartDefaultTask(void const * argument)
{
/* init code for LWIP */
MX_LWIP_Init();
/* USER CODE BEGIN 5 */
//-----------------------------------------------------------
struct netconn *conn;
err_t err;
conn = netconn_new(NETCONN_TCP);
if(conn!=NULL)
{
sock.conn = conn;
err = netconn_bind(conn, NULL, 80);
if(err == ERR_OK)
{
netconn_listen(conn);
sys_thread_new("tcp_thread", tcp_thread, (void*)&sock, DEFAULT_THREAD_STACKSIZE, osPriorityNormal);
}
else
{
netconn_delete(conn);
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_7, GPIO_PIN_SET); // LED RED
}
}
for(;;)
{
osDelay(1);
}
//-----------------------------------------------------------
/* USER CODE END 5 */
}
static void tcp_thread(void *arg)
{
err_t recv_err; // Variables for arguments (errors)
err_t err; // Variables for arguments (errors)
struct netconn *conn; // Structure for connection
struct netconn *newconn; // Structure for connection
struct netbuf *inbuf; // Pointer to connection buffer
struct_sock *arg_sock; // Pointer to arguments of task
arg_sock = (struct_sock*) arg;
conn = arg_sock->conn;
u16_t buflen;
char* buf;
struct fs_file file;
for(;;)
{
err = netconn_accept(conn, &newconn);
if (err == ERR_OK)
{
recv_err = netconn_recv(newconn, &inbuf); // Receiving the socket data in inbuf
if (recv_err == ERR_OK)
{
if (netconn_err(newconn) == ERR_OK)
{
netbuf_data(inbuf, (void**)&buf, &buflen);
if ((buflen >=5) && (strncmp(buf, "GET /", 5) == 0))
{
if ((strncmp((char const *)buf,"GET / ",6)==0)||(strncmp((char const *)buf,"GET /index.html",15)==0))
{
fs_open(&file, "/index.html");
netconn_write(newconn, (const unsigned char*)(file.data), (size_t)file.len, NETCONN_NOCOPY);
fs_close(&file);
}
else if (strncmp((char const *)buf,"GET /IMG/Test.png",17)==0)
{
fs_open(&file, "/IMG/Test.png");
netconn_write(newconn, (const unsigned char*)(file.data), (size_t)file.len, NETCONN_NOCOPY);
fs_close(&file);
}
else
{
fs_open(&file, "/404.html");
netconn_write(newconn, (const unsigned char*)(file.data), (size_t)file.len, NETCONN_NOCOPY);
fs_close(&file);
}
}
else
{
osDelay(1);
}
}
else
{
osDelay(1);
}
}
netbuf_delete(inbuf);
netconn_close(newconn);
netconn_delete(newconn);
}
else
{
osDelay(1);
}
}
}
Solved! Go to Solution.
2021-05-19 06:22 AM
Hello @DRude.1 ,
Updating the graph every second using post or get would be too heavy. Using WebSockets should help in this regard (a single continuous TCP connection, see this for some inspiration https://github.com/RealTimeLogic/MinnowServer).
Otherwise, it is possible to increase the maximum number of simultaneous connections using the MEMP_NUM_TCP_PCB macro, but it would use more memory and processor.
To ensure that connections are closed automatically after a certain timeout, you can follow this steps in this link: https://lwip.fandom.com/wiki/Netconn_receive_timeout
Finally, compressing the data that you're transmitting (something simple like differential compression) and relaxing some of the real-time constraints that you have (I don't know about your particular application, but using Bezier curves to interpolate between the samples thus reducing the throughput) should also help.
Best regards,
Walid
2021-05-06 04:05 AM
Hello @DRude.1 ,
Too many retransmissions and RST packets usually indicate a packet loss issue.
From the Wireshark trace, it seems that the board (192.168.1.195) is not the cause of retransmissions. Perhaps setting the HTTP clients timeout to something more forgiving would reduce them.
Otherwise, generally speaking, there does not seem to be an issue as the communication proceeds normally and is closed normally too. The traces don't look bad at all after all.
Could you please describe your setup?
Best Regards,
Walid
2021-05-06 08:49 AM
If you have FreeRTOS you may want to use their network library and driver instead of LwIP.
https://github.com/FreeRTOS/FreeRTOS-Plus-TCP
It should work well with FreeRTOS :)
-- p
2021-05-07 06:20 AM
Hi @Walid ZRELLI, I changed now the code of my HTPP server and added AJAX (it's for sending data array to HTTP client (browser) and building a chart of this array). So I have a couple of problems now. The first is a big delay with the renovation of the chart(It must be once to second because the client sends GET requests every 1000 msec) but in reality the chart brake and renovation once to 5-30 seconds. And the second one is a lot of RST/RST,ACK HTTP packages. So I feel like for everyone GET request the server creates a new connection, but do not close it.
Added to code
else if (strncmp((char const *)buf,"GET /js/Chart.min.js",20)==0)
{
fs_open(&file, "/js/Chart.min.js");
netconn_write(newconn, (const unsigned char*)(file.data), (size_t)file.len, NETCONN_NOCOPY);
fs_close(&file);
}
else if (strncmp((char const *)buf,"GET /content.bin",16)==0)
{
DynWebPage(newconn, arg_sock->y_pos);
}
Where DynWebPage generator of random number. It is just for example
void DynWebPage(struct netconn *conn, uint16_t y_pos)
{
portCHAR PAGE_BODY[1300];
uint16_t len = 0;
int i;
PAGE_BODY[0] = 0;
int val = 0;
sprintf(PAGE_BODY,"%s%s%s%s%drn%s",PAGE_HEADER_200_OK,PAGE_HEADER_SERVER,PAGE_HEADER_CONTENT_STREAM,PAGE_HEADER_LEN,1024,PAGE_HEADER_BYTES);
len = strlen(PAGE_BODY);
for(i=0;i<512;i++)
{
val = HAL_RNG_GetRandomNumber(&hrng)%4096;
PAGE_BODY[len + i * 2] = (uint8_t)val;
PAGE_BODY[len + i * 2 + 1] = (uint8_t)(val>>8);
}
netconn_write(conn, PAGE_BODY, strlen((char*)PAGE_BODY) + 1024, NETCONN_COPY);
}
And a example of Wireshark session. Also I can show html code of server
I use stm32f746 Nucleo board and PC (Google Chrome) with direct connection
2021-05-07 06:25 AM
@Pavel A. I lost a lot of time creating TCP and HTTP server with LWIP and It works almost well, I do not want to study something another, I prepare to fix what I have now. But thanks for advice
2021-05-19 06:22 AM
Hello @DRude.1 ,
Updating the graph every second using post or get would be too heavy. Using WebSockets should help in this regard (a single continuous TCP connection, see this for some inspiration https://github.com/RealTimeLogic/MinnowServer).
Otherwise, it is possible to increase the maximum number of simultaneous connections using the MEMP_NUM_TCP_PCB macro, but it would use more memory and processor.
To ensure that connections are closed automatically after a certain timeout, you can follow this steps in this link: https://lwip.fandom.com/wiki/Netconn_receive_timeout
Finally, compressing the data that you're transmitting (something simple like differential compression) and relaxing some of the real-time constraints that you have (I don't know about your particular application, but using Bezier curves to interpolate between the samples thus reducing the throughput) should also help.
Best regards,
Walid
2021-06-05 07:46 AM
> a good connection without errors, RST, retransmissions?
Also I can add that lwIP is significantly more flexible and can perform much better compared to +TCP stack from FreeRTOS.
2021-06-14 08:04 PM
@Piranha I saw your work about LWIP, but without program code support I can not apply it
2021-06-16 10:57 AM
And I thought you are a developer... Well, for Cube clickers the answer is simple - no, noone has gotten ST's network implementation working reliably because the HAL/Cube code is a broken bloatware written by incompetent "experts". You can write the code yourself, hire an actual developer, who can write code, or try some platform like ARM Mbed, ChibiOS. No other way around. Everything else is just marketing lies and fantasy.
2021-06-16 05:02 PM
Do Chibios or mbed have good ethernet drivers for STM32?