How to propertly close listener socket in TCP server

qaqa85
Posts: 4
Joined: Wed Jun 02, 2021 8:44 am

How to propertly close listener socket in TCP server

Postby qaqa85 » Fri Mar 11, 2022 2:16 pm

I got a little problem with propertly closing listener socket. I tried two methods:

1. First was just calling shutdown + close (but sometimes it isn't escaping socket accept function)
2. Second was forcing close by using SO_LINGER (but sometimes it's thow an error)
assertion "don't call tcp_abort/tcp_abandon for listen-pcbs" failed: file "C:/msys32/home/Dell/esp/esp-at/esp-idf/components/lwip/lwip/src/core/tcp.c", line 577, function: tcp_abandon
abort() was called at PC 0x402ae154 on core 0


The main reason is to close propertly socket or whole task.

My TCP_SERVICE_TASK

Code: Select all

static void tcp_server_task(void *pvParameters)
{
    char addr_str[128];
    int addr_family;
    int ip_protocol;

    STOP_TCP_TASK = 0;

    while (1)
    {
        if (STOP_TCP_TASK == 1) break;
        
#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(TCP_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(TCP_PORT);
        addr_family = AF_INET6;
        ip_protocol = IPPROTO_IPV6;
        inet6_ntoa_r(destAddr.sin6_addr, addr_str, sizeof(addr_str) - 1);
#endif

        int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
        if (listen_sock < 0)
        {
            KOSA_LOG(TAG, "Unable to create socket: errno %d", errno);
            break;
        }
        KOSA_LOG(TAG, "Socket created");

        if (STOP_TCP_TASK == 1)
        {
        	break;
        }
        
        int on = 1;
        int err = setsockopt (listen_sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on));
        KOSA_LOG(TAG, "Socket setsockopt err= %d", err);

        err = bind(listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr));
        KOSA_LOG(TAG, "Socket binded err= %d", err);
        if (err != 0)
        {
            KOSA_LOG(TAG, "Socket unable to bind: errno %d", errno);
            break;
        }

        if (STOP_TCP_TASK == 1)
        {
        	break;
        }

        err = listen(listen_sock, 1);
        if (err != 0)
        {
            KOSA_LOG(TAG, "Error occured during listen: errno %d", errno);
            break;
        }

        LISTEN_SOCKET = listen_sock;

        if (STOP_TCP_TASK == 1)
        {
        	break;
        }

        while (1)
        {  //listen loop
            KOSA_LOG(TAG, "Socket listening");

            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)
            {
                KOSA_LOG(TAG, "Unable to accept connection: errno %d", errno);
                break;
            } else
            {
                listen_loop(sock);
            }

            if (STOP_TCP_TASK == 1) break;

        }  
        
        shutdown(listen_sock, 0);
        close(listen_sock);
               // jeĹĽli jest to rozmyslne przerwanie suchania to konczÄ™ caly watek TCP
        if (STOP_TCP_TASK == 1) break;

    }  
    KOSA_LOG(TAG, "kosa_tcp_server_task END");
    STOP_TCP_TASK = 0;
    TCP_STATE = TCP_NOTHING;   //TCP is already close
    xSemaphoreGive(tcp_del_sem);
    vTaskDelete(NULL);
}
TCP_STOP_FUNCTION

Code: Select all

static void tcp_stop_code(void)
{
	    if (TCP_STATE == TCP_NOTHING) //TCP_STATE
	    {
	        KOSA_LOG(TAG,"Already stopped");
	    }
	    else
	    {
	    	tcp_del_sem = xSemaphoreCreateBinary();

        	KOSA_LOG(TAG,"Linger start");
	    	struct linger linger;
	    		linger.l_onoff = 1;
	    		linger.l_linger = 0;

	        if (PEER_CONNECTED == 0)
	        {
	            STOP_TCP_TASK = 1;
	            if (TCP_STATE == TCP_SERVER)
	            {
	            	if (setsockopt(LISTEN_SOCKET, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) == 0) {
		            	KOSA_LOG(TAG,"Linger ok");
		            	if (LISTEN_SOCKET != -1) close(LISTEN_SOCKET);
	            	}
	            	//if (shutdown(LISTEN_SOCKET, 0)) KOSA_LOG(TAG,"Cannot shutdown LISTEN_SOCKET");
	            	//if (shutdown(LISTEN_SOCKET, 0)) KOSA_LOG(TAG,"Cannot shutdown LISTEN_SOCKET");
	            	//if (close(LISTEN_SOCKET)) KOSA_LOG(TAG,"Cannot close LISTEN_SOCKET");  
	            }
	            else
	            {
	            	if (setsockopt(TCP_CLIENT_SOCK, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) == 0) {
	            		KOSA_LOG(TAG,"Linger ok");
	            		if (TCP_CLIENT_SOCK != -1) close(TCP_CLIENT_SOCK);
	            	}
	            //	if (shutdown(TCP_CLIENT_SOCK, 0)) KOSA_LOG(TAG,"Cannot shutdown CLIENT_SOCKET");
	            //	if (close(TCP_CLIENT_SOCK)) KOSA_LOG(TAG,"Cannot close CLIENT_SOCKET"); 
	            }
	        }
	        else
	        {
	            STOP_TCP_TASK = 1;
	            //if (shutdown(SEND_SOCKET, SHUT_RDWR)) KOSA_LOG(TAG,"Cannot shoutdown SEND_SOCKET");
	         	if (setsockopt(SEND_SOCKET, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) == 0) {
	         		KOSA_LOG(TAG,"Linger ok");
	        	    if (SEND_SOCKET != -1) close(SEND_SOCKET);
	        	}
	        }
	        KOSA_LOG(TAG,"Waiting for semaphore");
	        BaseType_t err = xSemaphoreTake(tcp_del_sem, portMAX_DELAY);
	        KOSA_LOG(TAG,"semaphore err - %d",err);
	       // KOSA_LOG(TAG,"Juz zastopowane");
	        vSemaphoreDelete(tcp_del_sem);
	    }
	    KOSA_LOG(TAG, "kosa_tcp_stop!");
}

Who is online

Users browsing this forum: No registered users and 84 guests