Now my question...
I want to build a wifi to Rs485 modbus konverter. I'm using tcp-ip socket. After i get a connection from a new client i want to close a old connection. This works fine for some time. I can connect from one client, then connect from a another client and it automatically closes the connection from the first client... and so on... but after about 10 times, i get the error 23 at accept().
It looks like this problem https://github.com/espressif/esp-idf/issues/2454
But i have already the latest version from the idf . The changes from f2d3efd in sockets.c are already in the file.
git describe gives me this Version number: v3.3-beta1-220-gdbca85f96
So maybe i do something wrong:
Here my Code
Code: Select all
static void connectionTask(void *arg )
{
// arg enthält einen Zeiger auf eine Verbindung
int *temp = (int*) arg;
int conn = *temp;
char rx_buffer[256];
int i;
connectionCount++;
while (1)
{
int len = recv(conn, rx_buffer, sizeof(rx_buffer), 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
{
rs485_write(rx_buffer,len);
}
}
//Dieser Punkt wird erreicht, wenn die Verbindung beendet wurde, oder ein Fehler aufgetreten ist.
//Verbindung schließen
shutdown(conn,2);
close(conn);
connectionCount--;
//Prüfe ob diese Verbindung die letzte noch offene war
if (connectionCount == 0)
{
//wenn ja, dann link led abschalten
LED_link_off();
}
//suche meinen Task und meine Verbindung in der Liste und setzte Sie auf 0
for (i = 0; i < MAX_CONNECTIONS; i++)
{
ESP_LOGI(TAG, "Found id %d in list position %d", conn,i);
if (connectionlist[i] == conn)
{
connectionlist[i] = 0;
tasklist[i] = 0;
break;
}
}
//Task wird beendet
vTaskDelete(NULL);
}
void tcp_server_task(void *pvParameters)
{
memset(connectionlist, 0, MAX_CONNECTIONS);
memset(tasklist, 0, MAX_CONNECTIONS);
char addr_str[128];
int addr_family;
int ip_protocol;
int listen_sock;
struct sockaddr_in6 destAddr;
int res;
#ifdef CONFIG_EXAMPLE_IPV4
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
bzero(&destAddr.sin6_addr.un, sizeof(destAddr.sin6_addr.un));
destAddr.sin6_family = AF_INET6;
destAddr.sin6_port = htons(CONFIG_rs485Port);
addr_family = AF_INET6;
ip_protocol = IPPROTO_IPV6;
inet6_ntoa_r(destAddr.sin6_addr, addr_str, sizeof(addr_str) - 1);
#endif
listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
if (listen_sock < 0) {
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
vTaskDelete(NULL);
return;
}
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);
vTaskDelete(NULL);
return;
}
ESP_LOGI(TAG, "Socket binded");
err = listen(listen_sock, 1);
if (err != 0) {
ESP_LOGE(TAG, "Error occured during listen: errno %d", errno);
vTaskDelete(NULL);
return;
}
ESP_LOGI(TAG, "Socket listening");
struct sockaddr_in6 sourceAddr; // Large enough for both IPv4 or IPv6
uint addrLen = sizeof(sourceAddr);
while (1)
{
connectionlist[i] = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen);
if (connectionlist[i] < 0) {
ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
continue;
}
ESP_LOGI(TAG, "New connection %d accepted, connection %d", connectionlist[i], i );
//neuen task starten
tasklist[i] = sys_thread_new("MODBUS CONNECTIONS TASK", connectionTask, ( void * ) &connectionlist[i], 2048, 5);
LED_link_on();
//nächste Verbindung auf der nächsten Position in der Verbindungslistelegen
i++;
///wenn maximale Verbindungsanzahl erreicht, dann wieder bei 0 anfangen,
//alte Verbindungen werden dann geschlossen
if (i >= MAX_CONNECTIONS)
{
i=0;
}
//falls auf der Verbindungsliste am Platz i bereits eine alte Verbindung besteht, diese Verbindung beenden und task löschen
if (connectionlist[i] != 0)
{
ESP_LOGI(TAG, "Close old connection number %d, connection id %d",i, connectionlist[i] );
vTaskDelete(tasklist[i]);
shutdown(connectionlist[i],2);;
res = close(connectionlist[i]);
if (res != 0)
{
ESP_LOGE(TAG, "Error closing old connection number %d, connection id %d",i, connectionlist[i] );
}
connectionlist[i] = 0;
tasklist[i] = 0;
}
}
vTaskDelete(NULL);
}