Problems with sockets and HTTP server
Posted: Mon Jan 25, 2021 8:19 pm
Hello,
I'm using ESP http server for my application with multiple web pages (html, png, js, css...).
I'm also using UDP client and server. I noticed that after 4 http calls I'm unable to open udp client socket.
This is my script:
-> HTTP server host a page called "/devicescan", the javascript call wait until 5 seconds for timeout
-> On the HTTP "get handler": an UDP server is openned on port 2000
-> Then and UDP client is openned and send a string to all other devices on the network via IP 192.168.1.255
-> UDP client is immediately closed
-> If the devices are present they answer back to the ESP on port 2000.
-> The UDP server wait for answers during two seconds and generate a json array.
-> After 2 seconds the answer is transfered back to the HTTP server.
For the example I receive this:
The page "/devicescan" works 4 times, but after this I receive this error: "UDP CLIENT: unable to create socket: errno 23"
I also tryed to use different port for client/server (eg 1800 and 1900).
If I wait a while, this is working again. I don't think I forgot to close the UDP socket, but maybe I'm reaching a limit somewhere or maybe the HTTP socket are not closed properely. How I can monitor this ?
I also noticed that I have a similar issue when I'm using the HTTP client.
Please find my code below:
get_handler function for the page /devicescann:
UDP client/server combined
Thank you for help.
I'm using ESP http server for my application with multiple web pages (html, png, js, css...).
I'm also using UDP client and server. I noticed that after 4 http calls I'm unable to open udp client socket.
This is my script:
-> HTTP server host a page called "/devicescan", the javascript call wait until 5 seconds for timeout
-> On the HTTP "get handler": an UDP server is openned on port 2000
-> Then and UDP client is openned and send a string to all other devices on the network via IP 192.168.1.255
-> UDP client is immediately closed
-> If the devices are present they answer back to the ESP on port 2000.
-> The UDP server wait for answers during two seconds and generate a json array.
-> After 2 seconds the answer is transfered back to the HTTP server.
For the example I receive this:
Code: Select all
{"scanlist":[{"name":"Dev1","ip":"192.168.1.193"},{"name":"Dev2","ip":"192.168.1.208"},{"name":"Dev3","ip":"192.168.1.221"}]}
I also tryed to use different port for client/server (eg 1800 and 1900).
If I wait a while, this is working again. I don't think I forgot to close the UDP socket, but maybe I'm reaching a limit somewhere or maybe the HTTP socket are not closed properely. How I can monitor this ?
I also noticed that I have a similar issue when I'm using the HTTP client.
Please find my code below:
get_handler function for the page /devicescann:
Code: Select all
static void page_devicescan(httpd_req_t *req)
{
char data[768]; //!\ 66 chars par device * 10 = 660 + marges
sprintf(data,"{\"scanlist\":[");
udp_server_start(data, sizeof(data));
strcat(data,"]}");
display_page(req, data, strlen(data));
}
Code: Select all
#define PORT_CLIENT 1900
#define PORT_SERVER 1800
static const char *TAGCLIENT = "[UDP CLIENT]";
static const char *TAGSERVER = "[UDP SERVER]";
static const char *payload = "UDP /NOTIFY-V5\r\n";
static esp_err_t udp_client_receive()
{
char addr_str[128];
int addr_family;
int ip_protocol;
char *HOST_IP_ADRESS;
HOST_IP_ADRESS=get_sta_ip();
uint8_t i;
for(i=strlen(HOST_IP_ADRESS); i>5; i--)
{
if(*(HOST_IP_ADRESS+i)=='.') break;
}
if(i==5)
{
ESP_LOGI(TAGCLIENT, "Can't match network with IP %s",HOST_IP_ADRESS);
return ESP_FAIL;
}
else
{
memcpy((HOST_IP_ADRESS+i+1),"255\0",4);
ESP_LOGI(TAGCLIENT, "Network is %s",HOST_IP_ADRESS);
struct sockaddr_in dest_addr;
dest_addr.sin_addr.s_addr = inet_addr(HOST_IP_ADRESS);
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(PORT_CLIENT);
addr_family = AF_INET;
ip_protocol = IPPROTO_IP;
inet_ntoa_r(dest_addr.sin_addr, addr_str, sizeof(addr_str) - 1);
int sock = socket(addr_family, SOCK_DGRAM, ip_protocol);
if (sock < 0)
{
ESP_LOGE(TAGCLIENT, "Unable to create socket: errno %d", errno);
return ESP_FAIL;
}
else
{
ESP_LOGI(TAGCLIENT, "Socket created, sending to %s:%d", HOST_IP_ADRESS, PORT_CLIENT);
int err = sendto(sock, payload, strlen(payload), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
if (err < 0)
{
ESP_LOGE(TAGCLIENT, "Error occurred during sending: errno %d", errno);
}
ESP_LOGI(TAGCLIENT, "Message sent");
ESP_LOGI(TAGCLIENT, "Shutting down socket.");
return ESP_OK;
}
shutdown(sock, 0);
close(sock);
}
}
void udp_server_start(char *scandata, uint16_t max_scandata_len)
{
int32_t l_free;
uint8_t is_first=1;
char sep[]=",";
char rx_buffer[128];
char addr_str[128];
//char tmp[50];
int addr_family;
int ip_protocol;
struct timeval timeout={2,0}; //set timeout for 2 seconds
struct sockaddr_in dest_addr;
dest_addr.sin_addr.s_addr = htonl(INADDR_ANY);
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(PORT_SERVER);
addr_family = AF_INET;
ip_protocol = IPPROTO_IP;
inet_ntoa_r(dest_addr.sin_addr, addr_str, sizeof(addr_str) - 1);
int sock = socket(addr_family, SOCK_DGRAM, ip_protocol);
if (sock < 0)
{
ESP_LOGE(TAGSERVER, "Unable to create socket: errno %d", errno);
}
else
{
ESP_LOGI(TAGSERVER, "Socket created");
int err = bind(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
if (err < 0)
{
ESP_LOGE(TAGSERVER, "Socket unable to bind: errno %d", errno);
}
else
{
ESP_LOGI(TAGSERVER, "Socket bound, port %d", PORT_SERVER);
setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(struct timeval));
if(udp_client_receive()==ESP_OK)
{
while (1)
{
ESP_LOGI(TAGSERVER, "Waiting for data");
struct sockaddr_in6 source_addr; // Large enough for both IPv4 or IPv6
socklen_t socklen = sizeof(source_addr);
int len = recvfrom(sock, rx_buffer, sizeof(rx_buffer) - 1, 0, (struct sockaddr *)&source_addr, &socklen);
// Error occurred during receiving
if (len < 0) {
ESP_LOGE(TAGSERVER, "recvfrom failed: errno %d", errno);
break;
}
// Data received
else
{
// Get the sender's ip address as string
if (source_addr.sin6_family == PF_INET)
{
inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1);
}
else if (source_addr.sin6_family == PF_INET6)
{
inet6_ntoa_r(source_addr.sin6_addr, addr_str, sizeof(addr_str) - 1);
}
rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string...
ESP_LOGI(TAGSERVER, "Received %d bytes from %s:", len, addr_str);
ESP_LOGI(TAGSERVER, "%s", rx_buffer);
if(strncmp(rx_buffer,"name=",5)==0 && strlen(rx_buffer)<=25)
{
l_free=max_scandata_len-(30+len+strlen(addr_str)+strlen(scandata)+1);
ESP_LOGI(TAGSERVER, "Free scanbuffer: %d of %d ",l_free, max_scandata_len);
if(l_free<=0)
{
ESP_LOGE(TAGSERVER, "Can't add aditionnal data, scanbuffer is full");
break;
}
}
else
{
ESP_LOGE(TAGSERVER, "Invalid data returned");
}
if(is_first==0) strcat(scandata,sep);
sprintf(scandata+strlen(scandata),"{\"name\":\"%s\",\"ip\":\"%s\"}",&rx_buffer[5],addr_str);
is_first=0;
int err = sendto(sock, rx_buffer, len, 0, (struct sockaddr *)&source_addr, sizeof(source_addr));
if (err < 0)
{
ESP_LOGE(TAGSERVER, "Error occurred during sending: errno %d", errno);
break;
}
}
}
ESP_LOGI(TAGSERVER, "Shutting down socket.");
}
else
{
ESP_LOGE(TAGSERVER, "Shutting down socket cause client errors");
}
}
}
shutdown(sock, 0);
close(sock);
}