0

I have tried to implement TCP client to send TCP keep alive request but all the option were failed with invalid argument. My code looks like as below:

    #define SERVER_ADDRESS "94.23.3.169" /* Server address */
    #define PORT 1010/* the port client will be connecting to */
    
    
    static int16_t i16Sockfd;
    
    void vEnablekeepalive(int16_t i16Sockfd;)
    {
        int16_t i16Enable;
        socklen_t optlen = sizeof(i16Enable);
    
        /* Check the status for the keepalive option */
        if(getsockopt(i16Sockfd, SOL_SOCKET, SO_KEEPALIVE, &i16Enable, &optlen) < 0) {
            perror("getsockopt");
        }
        MSG("Before KEEP_ALIVE OPTION:%d\n",i16Enable);
    
        i16Enable = 1;
        if(setsockopt(i16Sockfd, SOL_SOCKET, SO_KEEPALIVE, &i16Enable, sizeof(i16Enable)) == -1){
            perror("setsockopt");
        }
    
        /* Check the status for the keepalive option */
        if(getsockopt(i16Sockfd, SOL_SOCKET, SO_KEEPALIVE, &i16Enable, &optlen) < 0) {
            perror("getsockopt);
        }
        MSG("After KEEP_ALIVE OPTION:%d\n",i16Enable);
    
        int16_t i16Idle = 600;
        if(setsockopt(i16Sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &i16Idle, sizeof(i16Idle)) == -1){
            perror("Idle");
        }
    
        int16_t i16Interval = 60;
        if(setsockopt(i16Sockfd, IPPROTO_TCP, TCP_KEEPINTVL, &i16Interval, sizeof(i16Interval)) == -1){
            perror("Interval");
        }
    
        int16_t i16Maxcount = 5;
        if(setsockopt(i16Sockfd, IPPROTO_TCP, TCP_KEEPCNT, &i16Maxcount, sizeof(i16Maxcount)) == -1){
            perror("Maxcount");
        }
    }
    
    int main()
    {
        struct sockaddr_in their_addr;
        
        if ((i16Sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
            perror("socket");
        }
              
        Enablekeepalive(i16Sockfd);
    
        their_addr.sin_family = AF_INET; /* host byte order */
        their_addr.sin_port = htons(PORT); /* short, network byte order */
        their_addr.sin_addr.s_addr = inet_addr(SERVER_ADDRESS);
        zero(&(their_addr.sin_zero), 8); /* zero the rest of the struct */
        if (connect(i16Sockfd, (struct sockaddr*) &their_addr,sizeof(struct sockaddr)) == -1) {
            perror("connect");
            close(i16Sockfd);
        }
              
    }

I can't get why it is giving invalid argument for all setsockopt API. Is there anything wrong to set keep alive option using setsockopt?

  • 2
    Why are you using `int16_t` for all the places that require an `int`? They are likely not the same size on your system. – kaylum Sep 30 '20 at 04:41

2 Answers2

0

SO_KEEPALIVE is for a connection oriented socket. So please connect your socket first and set SO_KEEPALIVE after that.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • I have one more query: If i have enable keep alive and set all option for keep alive using above code then do i need to change below setting? **# echo 600 > /proc/sys/net/ipv4/tcp_keepalive_time # echo 60 > /proc/sys/net/ipv4/tcp_keepalive_intvl # echo 20 > /proc/sys/net/ipv4/tcp_keepalive_probes** – Abhishek Lakhara Oct 01 '20 at 07:01
  • @AbhishekLakhara: You don't need to change the settings if you can live with the current settings. Note that you can also apply socket specific settings for the keep alive timings - see https://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/#setsockopt – Steffen Ullrich Oct 01 '20 at 15:15
0

From the socket(7) documentation, which covers SO_XXX socket options:

The socket options listed below can be set by using setsockopt(2) and read with getsockopt(2) with the socket level set to SOL_SOCKET for all sockets. Unless otherwise noted, optval is a pointer to an int.

and

SO_KEEPALIVE Enable sending of keep-alive messages on connection-oriented sockets. Expects an integer boolean flag.

The Linux-specific TCP_KEEPIDLE etc. options also expect an int argument.

An int16_t like you're using as the option type is unlikely to be the same size as an int on typical systems these days, hence the errors. Use int instead.

Shawn
  • 47,241
  • 3
  • 26
  • 60