tcp_server example not able to reconnect the server after disconnect
-
- Posts: 2
- Joined: Wed Oct 10, 2018 8:32 pm
Re: tcp_server example not able to reconnect the server after disconnect
attached full code for TCP SERVER + SOFTAP + STA with bugfix of connection problems after disconnect and connect again.
+ fix with able to resume socket even after disconnecting and connecting back to the station or softap.
you can switch between station and softap by changing rf_mode value.
rf_mode = 0 for softap
rf_mode = 1 for station
+ fix with able to resume socket even after disconnecting and connecting back to the station or softap.
you can switch between station and softap by changing rf_mode value.
rf_mode = 0 for softap
rf_mode = 1 for station
- Attachments
-
- tcp_server.c
- (9.15 KiB) Downloaded 1003 times
-
- Posts: 2
- Joined: Wed Oct 10, 2018 8:32 pm
Re: tcp_server example not able to reconnect the server after disconnect
Another easy solution for this problem is to close server_socket(listen_sock) when we are closing the client socket(sock).
Add the highlighted line into tcp_server_task() function.
Add the highlighted line into tcp_server_task() function.
- if (sock != -1) {
- ESP_LOGE(TAG, "Shutting down socket and restarting...");
- shutdown(sock, 0);
- close(sock);
- close(listen_sock);
- }
- }
- vTaskDelete(NULL);
- }
Re: tcp_server example not able to reconnect the server after disconnect
But after a few closures and openings, error 112 returns!
Did anyone solve the problem permanently??Socket unable to bind: errno 112
-
- Posts: 12
- Joined: Thu Mar 23, 2017 3:05 am
Re: tcp_server example not able to reconnect the server after disconnect
hi,mikemoy and axellin ;
About your answer,you just move while(1) to listen above;
This modify do not close listen_socket and do not need to recreate new listen_socket, do not need to re-bind ,so you could work well in this case.
But if you need to change your PORT to other, this modify is not helpful ;
because you should work as this workflow, create server_socket,bind,accept,R/W client_socket, close server_socket;
This is my opinion;
About your answer,you just move while(1) to listen above;
This modify do not close listen_socket and do not need to recreate new listen_socket, do not need to re-bind ,so you could work well in this case.
But if you need to change your PORT to other, this modify is not helpful ;
because you should work as this workflow, create server_socket,bind,accept,R/W client_socket, close server_socket;
This is my opinion;
-
- Posts: 12
- Joined: Thu Mar 23, 2017 3:05 am
Re: tcp_server example not able to reconnect the server after disconnect
Update my test;
Added code close(listen_sock);after close(sock); its work well too;
but i have a question,i print out listen_sock ,it will be increased in every cycle;
Is it correctly?
Because i have been closed it in the end of cycle;I think the listen_sock will be released.
I (3114) example: Connected to AP
I (3114) example: Socket created id:54
I (3124) example: Socket binded
I (3124) example: Socket listening
I (9024) example: Socket accepted
I (11684) example: Received 4 bytes from 192.168.199.229:
I (11684) example: abcd
I (12294) example: Received 4 bytes from 192.168.199.229:
I (12294) example: abcd
I (12914) example: Received 4 bytes from 192.168.199.229:
I (12914) example: abcd
I (16594) example: Connection closed
E (16594) example: Shutting down socket and restarting...
I (16604) example: Socket created id:56
I (16604) example: Socket binded
I (16604) example: Socket listening
I (27964) example: Socket accepted
I (32774) example: Received 4 bytes from 192.168.199.229:
I (32774) example: abcd
I (33394) example: Received 4 bytes from 192.168.199.229:
I (33394) example: abcd
I (34014) example: Received 4 bytes from 192.168.199.229:
I (34014) example: abcd
I (45374) example: Connection closed
E (45374) example: Shutting down socket and restarting...
I (45374) example: Socket created id:58
I (45374) example: Socket binded
I (45384) example: Socket listening
Added code close(listen_sock);after close(sock); its work well too;
but i have a question,i print out listen_sock ,it will be increased in every cycle;
Is it correctly?
Because i have been closed it in the end of cycle;I think the listen_sock will be released.
I (3114) example: Connected to AP
I (3114) example: Socket created id:54
I (3124) example: Socket binded
I (3124) example: Socket listening
I (9024) example: Socket accepted
I (11684) example: Received 4 bytes from 192.168.199.229:
I (11684) example: abcd
I (12294) example: Received 4 bytes from 192.168.199.229:
I (12294) example: abcd
I (12914) example: Received 4 bytes from 192.168.199.229:
I (12914) example: abcd
I (16594) example: Connection closed
E (16594) example: Shutting down socket and restarting...
I (16604) example: Socket created id:56
I (16604) example: Socket binded
I (16604) example: Socket listening
I (27964) example: Socket accepted
I (32774) example: Received 4 bytes from 192.168.199.229:
I (32774) example: abcd
I (33394) example: Received 4 bytes from 192.168.199.229:
I (33394) example: abcd
I (34014) example: Received 4 bytes from 192.168.199.229:
I (34014) example: abcd
I (45374) example: Connection closed
E (45374) example: Shutting down socket and restarting...
I (45374) example: Socket created id:58
I (45374) example: Socket binded
I (45384) example: Socket listening
-
- Posts: 151
- Joined: Thu Jun 15, 2017 4:54 am
- Location: New Zealand
Re: tcp_server example not able to reconnect the server after disconnect
I've hit this problem with the example code too - and this thread is a bit confusing because it's not clear to me which changes apply to which other fixes. Does anyone have a working version of this example, for ESP-IDF v3.2, that correctly handles client disconnect/reconnects?
ESP guys - it would be really useful to have this example modified to fix this issue, please.
EDIT: this PR worked for me, but I agree that the architecture of this example isn't quite right - there should be no need to close and reopen/bind the listening socket each time a client disconnects.
ESP guys - it would be really useful to have this example modified to fix this issue, please.
EDIT: this PR worked for me, but I agree that the architecture of this example isn't quite right - there should be no need to close and reopen/bind the listening socket each time a client disconnects.
Re: tcp_server example not able to reconnect the server after disconnect
if (sock != -1)
{
ESP_LOGE(TAG, "Shutting down socket and restarting...");
shutdown(sock, 0);
close(sock);
shutdown(listen_sock,0);
close(listen_sock);
vTaskDelay(5);
}
{
ESP_LOGE(TAG, "Shutting down socket and restarting...");
shutdown(sock, 0);
close(sock);
shutdown(listen_sock,0);
close(listen_sock);
vTaskDelay(5);
}
Re: tcp_server example not able to reconnect the server after disconnect
Are you sure this is right?:
I'm still having difficulties here. I will try recompiling with v3.2.3.
The thing is, sock is set after listen_sock, so if accept() fails, then it won't shut down listen_sock. Which presumably messes it up, so subsequent connections will fail.
I think, maybe, this happens if you try to make two connections at the same time.
I'll investigate, but I don't think everything is full resolved.
Code: Select all
if (sock != -1) {
ESP_LOGE(TAG, "Shutting down socket and restarting...");
shutdown(sock, 0);
close(sock);
// mcarter 13-Sep-2019 err 112 fix. Ostensibly
shutdown(listen_sock, 0);
close(listen_sock);
vTaskDelay(5);
}
The thing is, sock is set after listen_sock, so if accept() fails, then it won't shut down listen_sock. Which presumably messes it up, so subsequent connections will fail.
I think, maybe, this happens if you try to make two connections at the same time.
I'll investigate, but I don't think everything is full resolved.
Re: tcp_server example not able to reconnect the server after disconnect
OK, I think I have gotten things to work better. Here's my revised code:
In all honesty I don't know how to write to TCP server, so I'm winging it a bit.
I've done a few things here:
* set up the listening socket in a separate function to modularise the code a bit
* if setting up the listening socket fails, then we forego an opportunity to serve TCP. We could presumably improve on this by looping on setup_listen_sock() if necessary. But I think that putting it in the while(1) loop is a bad idea.
* removed mention of shutdown(listen_socket, 0), close(listen_sock) within the sock != -1 block. Espressiv didn't have that code, but many people have suggested it. From what I can make of it, including it is a Bad idea (TM).
* I have changed LOGE to LOGI in the line "Shutting down socket and restarting...". I don't think it's an error; the client might decide to disconnect, and this isn't anything unusual.
Like I say, although the code above isn't perfect, I think it's better than what we had before.
The server won't respond to multiple TCP requests, but at least it won't mess up like it did before. Presumably we'd have to do some additional xTaskCreate's if we wanted to handle multiple connections.
Comments?
Code: Select all
int setup_listen_sock(int *ptr_listen_sock)
{
char addr_str[128];
int addr_family;
int ip_protocol;
int err = 0;
#ifdef CONFIG_EXAMPLE_IPV4
struct sockaddr_in destAddr;
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
struct sockaddr_in6 destAddr;
bzero(&destAddr.sin6_addr.un, sizeof(destAddr.sin6_addr.un));
destAddr.sin6_family = AF_INET6;
destAddr.sin6_port = htons(PORT);
addr_family = AF_INET6;
ip_protocol = IPPROTO_IPV6;
inet6_ntoa_r(destAddr.sin6_addr, addr_str, sizeof(addr_str) - 1);
#endif
*ptr_listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
if (*ptr_listen_sock < 0) {
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
return errno;
}
ESP_LOGI(TAG, "Socket created");
err = bind(*ptr_listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr));
if (err != 0) {
ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno);
return err;
}
ESP_LOGI(TAG, "Socket binded");
err = listen(*ptr_listen_sock, 1);
if (err != 0) {
ESP_LOGE(TAG, "Error occured during listen: errno %d", errno);
return err;
}
ESP_LOGI(TAG, "Socket listening");
return 0;
}
static void tcp_server_task(void *pvParameters)
{
char addr_str[128];
char rx_buffer[128];
int listen_sock;
int err = setup_listen_sock(&listen_sock);
if(err !=0) {
ESP_LOGE(TAG, "Listening socket unestablished. Server task will be deleted.");
vDeleteTask(NULL);
}
while (1) {
struct sockaddr_in6 sourceAddr; // Large enough for both IPv4 or IPv6
uint addrLen = sizeof(sourceAddr);
int sock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen);
if (sock < 0) {
ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
break;
}
ESP_LOGI(TAG, "Socket accepted");
while (1) {
int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 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 {
// Get the sender's ip address as string
if (sourceAddr.sin6_family == PF_INET) {
inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1);
} else if (sourceAddr.sin6_family == PF_INET6) {
inet6_ntoa_r(sourceAddr.sin6_addr, addr_str, sizeof(addr_str) - 1);
}
rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
ESP_LOGI(TAG, "Received %d bytes from %s:", len, addr_str);
ESP_LOGI(TAG, "%s", rx_buffer);
// --- YOUR CODE HERE ---
int err = send(sock, rx_buffer, strlen(rx_buffer), 0);
if (err < 0) {
ESP_LOGE(TAG, "Error occured during sending: errno %d", errno);
break;
}
}
}
if (sock != -1) {
ESP_LOGI(TAG, "Shutting down socket and restarting...");
shutdown(sock, 0);
close(sock);
vTaskDelay(5);
}
}
vTaskDelete(NULL);
}
I've done a few things here:
* set up the listening socket in a separate function to modularise the code a bit
* if setting up the listening socket fails, then we forego an opportunity to serve TCP. We could presumably improve on this by looping on setup_listen_sock() if necessary. But I think that putting it in the while(1) loop is a bad idea.
* removed mention of shutdown(listen_socket, 0), close(listen_sock) within the sock != -1 block. Espressiv didn't have that code, but many people have suggested it. From what I can make of it, including it is a Bad idea (TM).
* I have changed LOGE to LOGI in the line "Shutting down socket and restarting...". I don't think it's an error; the client might decide to disconnect, and this isn't anything unusual.
Like I say, although the code above isn't perfect, I think it's better than what we had before.
The server won't respond to multiple TCP requests, but at least it won't mess up like it did before. Presumably we'd have to do some additional xTaskCreate's if we wanted to handle multiple connections.
Comments?
-
- Posts: 151
- Joined: Thu Jun 15, 2017 4:54 am
- Location: New Zealand
Who is online
Users browsing this forum: ShreyAcharya and 109 guests