How to set the "sendto" function as a blocking?

jason2
Posts: 44
Joined: Thu Oct 26, 2017 11:02 am

How to set the "sendto" function as a blocking?

Postby jason2 » Thu Jan 04, 2018 6:48 am

"sendto" is a UDP API.It's non_blocking API.How to set "sendto" as blocking mode.Blocking to sending buffer is enough.I have tried "select" API,but it dosen't work.
Can "sendto" API be set as blocking mode?

ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: How to set the "sendto" function as a blocking?

Postby ESP_Angus » Fri Jan 05, 2018 12:03 am

Hi jason,

I'm a little confused by your question. By default, a UDP socket is blocking and if the UDP buffer is full then sendto() will block.

If you set the socket as non-blocking via something like fctnl(fd, F_SETFL, O_NONBLOCK) then it will become non-blocking and sendto() will return with errno==EWOULDBLOCK if a call would have blocked because the send buffer is full.

If you need to make the socket blocking again then you can call fcntl(fd, F_SETFL, 0)

If you're seeing different behaviour, can you please post some code which shows this behaviour?

Angus

jason2
Posts: 44
Joined: Thu Oct 26, 2017 11:02 am

Re: How to set the "sendto" function as a blocking?

Postby jason2 » Fri Jan 05, 2018 5:58 am

By default, a UDP socket is blocking and if the UDP buffer is full then "sendto" will block
"If the UDP buffer is full then "sendto" will block".So why the "sendto" return fail and fail reason is ENOMEM.
If you need to make the socket blocking again then you can call fcntl(fd, F_SETFL, 0)
I tried fcntl(fd, F_SETFL, 0).But "sendto" still return fails and fail reason is ENOMEM.

I want to make "sendto" send packet if buffer is enough.If buffer is not enough,I want to make "sento" block until the moment that buffer is enough.

My sample code:

Code: Select all

#include <string.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 "esp_wifi_types.h"
#include "esp_task_wdt.h"

#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"
#include "lwip/api.h"
#include "lwip/netbuf.h"


#define TEST_BUFFER_ADDRESS 0x3f400000
#define EXAMPLE_WIFI_SSID "jason888"
#define EXAMPLE_WIFI_PASS "wise6688"
#define REMOTE_PORT 1112

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

/* The event group allows multiple bits for each event,
   but we only care about one event - are we connected
   to the AP with an IP? */
const int CONNECTED_BIT = BIT0;

static const char *TAG = "Log_Test";
#define SEND_BUF_LEN 480
#define SEND_START_LEN 5
#define SEND_END_LEN 3
const unsigned char start[5]="start";
const unsigned char end[3]="end";
unsigned char test_buffer[1440];


static void udp_thread(void *p)
{
	int i = 0;
	int ret=0;
	int sock;
	struct sockaddr_in toAddr;
  
	
	LWIP_UNUSED_ARG(p);

	sock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
	if(sock < 0)
	{
		ESP_LOGI(TAG, "socket err");
	}
        
        fcntl(sock,F_SETFL,0);

	memset(&toAddr,0,sizeof(toAddr));
	toAddr.sin_family=AF_INET;
	toAddr.sin_addr.s_addr=inet_addr("192.168.43.1");
	toAddr.sin_port = htons(REMOTE_PORT);
	printf("test_buffer is %p",test_buffer);
	int fail_count=0;
	while(1) {
	xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
		sendto(sock,start,SEND_START_LEN,0,(struct sockaddr*)&toAddr,sizeof(toAddr));
		
		for(i=0; i<80; i++)
		{
			vTaskDelay(1/portTICK_RATE_MS);
		
			ret=sendto(sock,test_buffer,1440,0,(struct sockaddr*)&toAddr,sizeof(toAddr));
			
			if(ret<0)
			{
				
					perror("fail reason is:\n");
                                        fail_count++;
			}
			
		}
		
	  	vTaskDelay(400/portTICK_RATE_MS);     
		printf("fail_count=%d\n",fail_count);
		fail_count=0;
		sendto(sock,end,SEND_END_LEN,0,(struct sockaddr*)&toAddr,sizeof(toAddr));
	}
	close(sock);
	vTaskDelete(NULL);
}

static void udp_client_init(void)
{
	int ret;
	ret = xTaskCreate(&udp_thread, "udp_client_task", 2048, NULL, 5, NULL);
	if(ret != pdPASS) 
        {
		ESP_LOGI(TAG, "create thread udp_client_task failed");
	}
        	
}

static esp_err_t event_handler(void *ctx, system_event_t *event)
{
    switch(event->event_id) {
    case SYSTEM_EVENT_STA_START:
        esp_wifi_connect();
        break;
    case SYSTEM_EVENT_STA_GOT_IP:
        xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
		udp_client_init();
        break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
        esp_wifi_connect();
        xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
        break;
    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) );
    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(WIFI_IF_STA, &wifi_config) );
    ESP_ERROR_CHECK( esp_wifi_start());
    esp_wifi_set_ps(WIFI_PS_MODEM);
}   

void app_main()
{

    	nvs_flash_init();
	initialise_wifi();
}

ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: How to set the "sendto" function as a blocking?

Postby ESP_Angus » Fri Jan 05, 2018 6:19 am

Ah, I see. Sorry, I forgot about the ENOMEM issue. This relates to the WiFi driver blocking as the low-level buffers are full.

We've discussed with the wifi team about optionally changing this behaviour in a future release, but for now the best thing you can do is check for errno==ENOMEM and retry. Sorry about that.

WiFive
Posts: 3529
Joined: Tue Dec 01, 2015 7:35 am

Re: How to set the "sendto" function as a blocking?

Postby WiFive » Fri Jan 05, 2018 6:21 am

https://github.com/espressif/esp-idf/issues/390

(1/portTICK_RATE_MS) will be zero if your tick rate is <1000

Who is online

Users browsing this forum: No registered users and 124 guests