Socket - TCP Server 500ms read time out

belph86
Posts: 6
Joined: Sat Mar 30, 2019 11:03 pm

Socket - TCP Server 500ms read time out

Postby belph86 » Sat Mar 30, 2019 11:09 pm

Recently I tried one of examples in IDF for Sockets - TCP Server.

Once socket is binded, my python client is able to get write,read response every 500ms.

Is it possible to speed it up ? No matter what size the buffer is. Response time is the same.

I have checked all settings in menuconfig for TCP or LWIP settings. No luck there.

Is it possible to speed it up ?


Thanks a lot in advance for response

ESP_Sprite
Posts: 9617
Joined: Thu Nov 26, 2015 4:08 am

Re: Socket - TCP Server 500ms read time out

Postby ESP_Sprite » Sun Mar 31, 2019 5:35 am

Hard to say without code or more information about what you're trying to do, but perhaps you're running into a drawback of Nagles algorithm on either side?

belph86
Posts: 6
Joined: Sat Mar 30, 2019 11:03 pm

Re: Socket - TCP Server 500ms read time out

Postby belph86 » Sun Mar 31, 2019 12:07 pm

I have used example code from espressif socket tcp server.

In my pc I run python socket client and send message “hello world” or 128 bytes message.
Either way I get response 0.5s and unable to speed it up.
I need to send frequent message like 100ms.
Has anybody tried example code socket server client on two esps 32 with higher speed?

belph86
Posts: 6
Joined: Sat Mar 30, 2019 11:03 pm

Re: Socket - TCP Server 500ms read time out

Postby belph86 » Mon Apr 01, 2019 6:34 pm

ESP_Sprite wrote:
Sun Mar 31, 2019 5:35 am
Hard to say without code or more information about what you're trying to do, but perhaps you're running into a drawback of Nagles algorithm on either side?
It is not related to nagles algorithm. I have tried example esp-Idf TCP Client. Sending 128bytes long message from ESP32 to TCP server running on PC. Rate was around 50ms as I declared. But it does not work for TCP server. It is exact example of esp-Idf . Just changed wifi credentials and defined message.

I believe there is some time out of 500ms in code. Something I have missing to add config variable or message ending. I have even tried to put at the end of message \n \l . With UART I had this issue. But none of it worked :( .

belph86
Posts: 6
Joined: Sat Mar 30, 2019 11:03 pm

Re: Socket - TCP Server 500ms read time out

Postby belph86 » Mon Apr 01, 2019 6:36 pm

ESP_Sprite wrote:
Sun Mar 31, 2019 5:35 am
Hard to say without code or more information about what you're trying to do, but perhaps you're running into a drawback of Nagles algorithm on either side?
This is the code

Code: Select all

/* BSD Socket API Example
   This example code is in the Public Domain (or CC0 licensed, at your option.)
   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include <sys/param.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "nvs_flash.h"

#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>


/* The examples use simple WiFi configuration that you can set via
   'make menuconfig'.
   If you'd rather not, just change the below entries to strings with
   the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/
#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID
#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD

#define PORT CONFIG_EXAMPLE_PORT

/* FreeRTOS event group to signal when we are connected & ready to make a request */
static EventGroupHandle_t wifi_event_group;

const int IPV4_GOTIP_BIT = BIT0;
const int IPV6_GOTIP_BIT = BIT1;

static const char *TAG = "example";

static esp_err_t event_handler(void *ctx, system_event_t *event)
{
    switch (event->event_id) {
    case SYSTEM_EVENT_STA_START:
        esp_wifi_connect();
        ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START");
        break;
    case SYSTEM_EVENT_STA_CONNECTED:
        /* enable ipv6 */
        tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA);
        break;
    case SYSTEM_EVENT_STA_GOT_IP:
        xEventGroupSetBits(wifi_event_group, IPV4_GOTIP_BIT);
        ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP");
        break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
        /* This is a workaround as ESP32 WiFi libs don't currently auto-reassociate. */
        esp_wifi_connect();
        xEventGroupClearBits(wifi_event_group, IPV4_GOTIP_BIT);
        xEventGroupClearBits(wifi_event_group, IPV6_GOTIP_BIT);
        break;
    case SYSTEM_EVENT_AP_STA_GOT_IP6:
        xEventGroupSetBits(wifi_event_group, IPV6_GOTIP_BIT);
        ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP6");

        char *ip6 = ip6addr_ntoa(&event->event_info.got_ip6.ip6_info.ip);
        ESP_LOGI(TAG, "IPv6: %s", ip6);
    default:
        break;
    }
    return ESP_OK;
}

static void initialise_wifi(void)
{
    tcpip_adapter_init();
    wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
    ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = EXAMPLE_WIFI_SSID,
            .password = EXAMPLE_WIFI_PASS,
        },
    };
    ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid);
    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
    ESP_ERROR_CHECK( esp_wifi_start() );
}

static void wait_for_ip()
{
    uint32_t bits = IPV4_GOTIP_BIT | IPV6_GOTIP_BIT ;

    ESP_LOGI(TAG, "Waiting for AP connection...");
    xEventGroupWaitBits(wifi_event_group, bits, false, true, portMAX_DELAY);
    ESP_LOGI(TAG, "Connected to AP");
}

static void tcp_server_task(void *pvParameters)
{
    char rx_buffer[128];
    char addr_str[128];
    int addr_family;
    int ip_protocol;

    while (1) {

#ifdef CONFIG_EXAMPLE_IPV4
        struct sockaddr_in destAddr;
        destAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        destAddr.sin_family = AF_INET;
        destAddr.sin_port = htons(PORT);
        addr_family = AF_INET;
        ip_protocol = IPPROTO_IP;
        inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1);
#else // IPV6
        struct sockaddr_in6 destAddr;
        bzero(&destAddr.sin6_addr.un, sizeof(destAddr.sin6_addr.un));
        destAddr.sin6_family = AF_INET6;
        destAddr.sin6_port = htons(PORT);
        addr_family = AF_INET6;
        ip_protocol = IPPROTO_IPV6;
        inet6_ntoa_r(destAddr.sin6_addr, addr_str, sizeof(addr_str) - 1);
#endif

        int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
        if (listen_sock < 0) {
            ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
            break;
        }
        ESP_LOGI(TAG, "Socket created");

        int err = bind(listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr));
        if (err != 0) {
            ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno);
            break;
        }
        ESP_LOGI(TAG, "Socket binded");

        err = listen(listen_sock, 1);
        if (err != 0) {
            ESP_LOGE(TAG, "Error occured during listen: errno %d", errno);
            break;
        }
        ESP_LOGI(TAG, "Socket listening");

        struct sockaddr_in6 sourceAddr; // Large enough for both IPv4 or IPv6
        uint addrLen = sizeof(sourceAddr);
        int sock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen);
        if (sock < 0) {
            ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
            break;
        }
        ESP_LOGI(TAG, "Socket accepted");

        while (1) {
            int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
            // Error occured during receiving
            if (len < 0) {
                ESP_LOGE(TAG, "recv failed: errno %d", errno);
                break;
            }
            // Connection closed
            else if (len == 0) {
                ESP_LOGI(TAG, "Connection closed");
                break;
            }
            // Data received
            else {
                // Get the sender's ip address as string
                if (sourceAddr.sin6_family == PF_INET) {
                    inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1);
                } else if (sourceAddr.sin6_family == PF_INET6) {
                    inet6_ntoa_r(sourceAddr.sin6_addr, addr_str, sizeof(addr_str) - 1);
                }

                rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
                ESP_LOGI(TAG, "Received %d bytes from %s:", len, addr_str);
                ESP_LOGI(TAG, "%s", rx_buffer);

                int err = send(sock, rx_buffer, len, 0);
                if (err < 0) {
                    ESP_LOGE(TAG, "Error occured during sending: errno %d", errno);
                    break;
                }
            }
        }

        if (sock != -1) {
            ESP_LOGE(TAG, "Shutting down socket and restarting...");
            shutdown(sock, 0);
            close(sock);
        }
    }
    vTaskDelete(NULL);
}

void app_main()
{
    ESP_ERROR_CHECK( nvs_flash_init() );
    initialise_wifi();
    wait_for_ip();

    xTaskCreate(tcp_server_task, "tcp_server", 4096, NULL, 5, NULL);
}

ESP_cermak
Posts: 69
Joined: Thu Nov 01, 2018 8:32 am

Re: Socket - TCP Server 500ms read time out

Postby ESP_cermak » Mon Apr 01, 2019 8:02 pm

Hi belph86,

the idf tcp_server example receives a message from a blocking socket and echos it back. if you're talking about the delay between esp32 sending the message and its reception in python, then indeed this could be Nagles algorithm. You can set the socket to nodelay mode with:

Code: Select all

        int nodelay = 1;
        setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *)&nodelay, sizeof(int));

belph86
Posts: 6
Joined: Sat Mar 30, 2019 11:03 pm

Re: Socket - TCP Server 500ms read time out

Postby belph86 » Tue Apr 02, 2019 10:40 pm

Hi Cermak.

You are right ! 8-) Thank you very much. Also ESP_Sprite your guess was very right. Thanks guys !

Delay is very convenient now. Sometimes every 20-40th message gets delayed by 400ms-1s. Then CPU starts working fast again.
I have set priority of task to 2. Still gets this issue.

Am I missing additional parameter to set ?

ESP_Sprite
Posts: 9617
Joined: Thu Nov 26, 2015 4:08 am

Re: Socket - TCP Server 500ms read time out

Postby ESP_Sprite » Wed Apr 03, 2019 4:09 am

Could be retransmits; if a packet gets 'lost', tcp waits a while for the ack to arrive, and only re-sends after a while. This is a quirk of the protocol; if you don't want to wait for acks (or if you want to handle them yourself in your own protocol), you're better off using UDP.

rews77@naver.com
Posts: 1
Joined: Fri May 17, 2024 12:52 am

Re: Socket - TCP Server 500ms read time out

Postby rews77@naver.com » Fri May 17, 2024 9:03 am

I also had a similar problem.
If you know, please let me know

I created an ESP-IDF 5.2 example tcp_client project.
I connected esp32(wifi) to the PC server(wifi) and immediately sent the data received from the server. (12345)
However, I was able to receive the data sent from the PC server after about 100ms.
Why is there a delay?
It takes the same time on esp32 Arduino.
It takes about 2m to perform the same operation between the Raspberry Pi (wifi) client and the PC server (wifi).

esp32 ESP-IDF 5.2 example Is there anything I need to configure in the tcp_client project?

Example) Interrupt time, thread time, etc.

help me..

Who is online

Users browsing this forum: No registered users and 87 guests