Public

Content is public and is viewable by everyone.

Keep Alive Timer - detecting idle or dead network connections'

    TCP's keep alive timer can be used to detect the idle or dead network connections. This can also be used to detect machine crashes. Keep alive timer is one of the TCP timers that periodically sends a keep alive probe with the ACK flag turned on. In response the recepient will send an ACK without any data, so it seamlessly works with the underlying tcp connection. If there is no response for predefined number of keepalive probes then the connection gets terminated. Recipient of the keep alive probe do not need any additional functionality as keep alive probes are just like any normal TCP packets. Senders has to enable the keep alive functionality using setsockopt on the tcp socket.

     

    With lwIP by default the first keep alive probe will be sent after 2 hours and if there is no response then subsequent probes will be sent at every 1.25 sec apart. If there is no reply for 9 keep alive probes the connection will be terminated. These default macros that control the various times of keep alive timer can be found in \lib\src\lwip\src\include\lwip\tcp.h as given below

     

    #ifndef TCP_KEEPIDLE_DEFAULT
    #define TCP_KEEPIDLE_DEFAULT 7200000UL
    /* Default KEEPALIVE timer in milliseconds */
    #endif
    #ifndef TCP_KEEPINTVL_DEFAULT
    #define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */
    #endif
    #ifndef TCP_KEEPCNT_DEFAULT
    #define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */

     

    The above default values are conformed to RFC1122. You may change the values depending on your application requirements but be aware that decreasing the timeouts may un-necessarily send keep alive probes costing the network bandwidth. If you change any of the above default values in the tcp.h then you have to recompile the lwIP library (liblwIPBF5xxx.dlb) .Note that keepalive timeout may wrongly close the connections because of transient network failures.
    You can also set the above keep alive parameters by using setsockopt() using the following options
      TCP_KEEPALIVE : set idle time in milliseconds
      TCP_KEEPIDLE   : set idle time in seconds
      TCP_KEEPINTVL : set keep alive time interval
      TCP_KEEPCNT    : set number of keep alive probes.

     

    In the below example tcp keep alive timer is used to detect idle connection. The blocking recv call returns as keep alive closes connection upon keep alive timeout.

     

    #define SERV_HOST_ADDR "192.168.1.40"
    #define SERV_HOST_PORT 8000

    void receiver(void)
    {
        int socket_fd, ret;
        struct sockaddr_in serv_addr;
        int num_recv_bytes =0;
        int val=1;
        int keepalive_idle_time = 5000; /* number of milli seconds */

        if ((socket_fd = socket(AF_INET,SOCK_STREAM,0)) == -1)
        {
            return; // error
        }

        memset((char *)&serv_addr,0,sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
            serv_addr.sin_addr.s_addr = inet_addr(SERV_HOST_ADDR);
            serv_addr.sin_port = htons(SERV_TCP_PORT);

        /* set the idle time after which tcp keepalive probes should start */
            if( setsockopt(socket_fd,IPPROTO_TCP,TCP_KEEPALIVE,(void*)&keepalive_idle_time,sizeof(keepalive_idle_time)) == -1)
        {
            printf("setsockopt TCP_KEEPALIVE failed\n");
            return;
        }

        if( setsockopt(socket_fd,SOL_SOCKET,SO_KEEPALIVE,(void*)&val,sizeof(val)) == -1)
        {
          printf("setsockopt SO_KEEPALIVE failed\n");
          return;
        }

        if (connect(socket_fd,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) <0)
        {
                    ret = send(socket_fd,buffer,strlen(buffer),0);
            // Receive the same string, if idle then break
            //
            memset(rcv_buffer,0,sizeof(rcv_buffer));

                    while(1)
                    {
                            num_recv_bytes = recv(socket_fd,rcv_buffer,BUFFER_LENGTH,0);
                            if(num_recv_bytes < 0)
                            {
                                    printf("Receiver: failed exiting\n",buffer);
                                    return;
                            }
                            else if (num_recv_bytes == 0)
                            {
                                    /*
                                    Connection is closed by the tcp keep alive timer upon timeout
                                    we will break out of the while loop and close the
                                    socket.
                                    */
                                    printf("Connection IDLE Keep-Alive timer terminated connection\n");
                                    break;
                            }
                    }

                    // close the socket
                    close(socket_fd);
            }
    }