"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?
How to set the "sendto" function as a blocking?
Re: How to set the "sendto" function as a blocking?
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
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
Re: How to set the "sendto" function as a blocking?
"If the UDP buffer is full then "sendto" will block".So why the "sendto" return fail and fail reason is ENOMEM.By default, a UDP socket is blocking and if the UDP buffer is full then "sendto" will block
I tried fcntl(fd, F_SETFL, 0).But "sendto" still return fails and fail reason is ENOMEM.If you need to make the socket blocking again then you can call fcntl(fd, F_SETFL, 0)
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();
}
Re: How to set the "sendto" function as a blocking?
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.
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.
Re: How to set the "sendto" function as a blocking?
https://github.com/espressif/esp-idf/issues/390
(1/portTICK_RATE_MS) will be zero if your tick rate is <1000
(1/portTICK_RATE_MS) will be zero if your tick rate is <1000
Who is online
Users browsing this forum: Dennie and 107 guests