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();
}