tcp_server example not able to reconnect the server after disconnect

dhavalpatel0114
Posts: 2
Joined: Wed Oct 10, 2018 8:32 pm

Re: tcp_server example not able to reconnect the server after disconnect

Postby dhavalpatel0114 » Tue Nov 06, 2018 7:29 pm

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
Attachments
tcp_server.c
(9.15 KiB) Downloaded 1002 times

dhavalpatel0114
Posts: 2
Joined: Wed Oct 10, 2018 8:32 pm

Re: tcp_server example not able to reconnect the server after disconnect

Postby dhavalpatel0114 » Fri Nov 16, 2018 7:28 pm

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.
  1.  
  2.  if (sock != -1) {
  3.             ESP_LOGE(TAG, "Shutting down socket and restarting...");
  4.             shutdown(sock, 0);
  5.             close(sock);
  6.             close(listen_sock);
  7.         }
  8.     }
  9.     vTaskDelete(NULL);
  10. }

adam_esp
Posts: 37
Joined: Mon Apr 29, 2019 12:09 pm

Re: tcp_server example not able to reconnect the server after disconnect

Postby adam_esp » Tue Apr 30, 2019 8:00 am

But after a few closures and openings, error 112 returns!
Socket unable to bind: errno 112
Did anyone solve the problem permanently??

tangqingcai
Posts: 12
Joined: Thu Mar 23, 2017 3:05 am

Re: tcp_server example not able to reconnect the server after disconnect

Postby tangqingcai » Mon May 13, 2019 8:08 am

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;

tangqingcai
Posts: 12
Joined: Thu Mar 23, 2017 3:05 am

Re: tcp_server example not able to reconnect the server after disconnect

Postby tangqingcai » Mon May 13, 2019 8:35 am

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

meowsqueak
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

Postby meowsqueak » Thu Jun 06, 2019 11:03 pm

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.

yuanyijie
Posts: 2
Joined: Sat Jul 27, 2019 8:49 am

Re: tcp_server example not able to reconnect the server after disconnect

Postby yuanyijie » Sat Jul 27, 2019 8:58 am

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

blippy
Posts: 17
Joined: Tue Jun 25, 2019 7:36 am

Re: tcp_server example not able to reconnect the server after disconnect

Postby blippy » Mon Sep 16, 2019 4:20 pm

Are you sure this is right?:

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

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.

blippy
Posts: 17
Joined: Tue Jun 25, 2019 7:36 am

Re: tcp_server example not able to reconnect the server after disconnect

Postby blippy » Mon Sep 16, 2019 5:52 pm

OK, I think I have gotten things to work better. Here's my revised code:

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

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?

meowsqueak
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

Postby meowsqueak » Mon Sep 16, 2019 11:20 pm

blippy wrote:
Mon Sep 16, 2019 5:52 pm
Comments?
Did you try the PR I linked to? I didn't have any problems with it, but my use case may be different.

Who is online

Users browsing this forum: No registered users and 113 guests