title: Proper use of getsockopt and setsockopt for SO_RCVTIMEO and SO_SNDTIMEO
body: <p>By various reasons I would like to implement timeout on reading and writing to socket in a server but fail to get it running and therefore kindly ask for some insight into wherein the problem may reside. </p>
  
  <p>In order to set the timeout on the read and write to the socket I'm trying to use of the functions <code>setsocketopt()</code> and <code>getsocketopt()</code>. However I must be doing something wrong as the return value indicates that a problem have occurred and perror outputs "Invalid argument". Strangely enough the error does not always occur at the first usage of <code>setsocketopt()</code> and <code>getsocketopt()</code>, which puzzles me bit. </p>
  
  <p>The following server and client codes reproduces my problems (compiled using gcc)  </p>
  
  <p>server code:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;string.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;netdb.h&gt;
  #include &lt;sys/socket.h&gt; 
  #include &lt;netinet/in.h&gt; 
  #include &lt;arpa/inet.h&gt;  
  
  int main() {
     struct sockaddr_in saddr,caddr; 
     socklen_t clen;
     int sock, csock, reuse = 1, ret=0;
     socklen_t ntrcv, ntsnd;
     struct timeval tout, tsnd, trcv;
  
     // create a new stream socket
     if ((sock = socket(AF_INET, SOCK_STREAM, 0)) &lt; 0) perror("failed to create socket");
     else {          
        // enable the socket to reuse the address
        if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &amp;reuse, sizeof(reuse)) &lt; 0) perror("failed allowing server socket to reuse address");
        else {
           // set up the server address
           memset((char *) &amp;saddr, 0, sizeof(saddr));
           saddr.sin_family = AF_INET;
           saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
           saddr.sin_port = htons(45454);
  
           // bind socket to address
           if (bind(sock, (struct sockaddr *) &amp;saddr, sizeof(saddr)) &lt; 0) perror("failed to bind");
           else {
              // listen to the socket for connections 
              if (listen(sock,5) &lt; 0) perror("failed to listen");
              else {
                 clen = sizeof(caddr);
                 if ((csock = accept(sock, (struct sockaddr *) &amp;caddr, &amp;clen)) &lt; 0) perror("failed to accept");
                 else {
                    tout.tv_sec=0;
                    tout.tv_usec=10000;
  
                    // check value of errno prior to setting timeout
                    perror("errno prior to timeout");
  
                    if (getsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &amp;trcv, &amp;ntrcv) &lt; 0) perror("2");
                    else if (getsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &amp;tsnd, &amp;ntsnd) &lt; 0) perror("3");
                    else if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &amp;tout, sizeof(tout)) &lt; 0) perror("4");
                    else if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &amp;tout, sizeof(tout)) &lt; 0) perror("5");
                    else {
                       printf ("all ok so far in server\n");
                   sleep(1);
                       if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &amp;trcv, ntrcv) &lt; 0) perror("6");
                       else if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &amp;tsnd, ntsnd) &lt; 0) perror("7");
                    }
                    if (close(csock) &lt; 0) perror("failed to close csock");
                 }
              }
           }
        }
     }
     if (close(sock) &lt; 0) perror("failed to close sock");
     return ret;
  }
  </code></pre>
  
  <p>client code:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;string.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;netdb.h&gt;
  #include &lt;sys/socket.h&gt;
  #include &lt;netinet/in.h&gt;
  #include &lt;arpa/inet.h&gt;
  
  int main() {
     struct sockaddr_in addr;     
     struct hostent *server; 
     int sock = 0;
  
     // resolve server name
     if (!(server = gethostbyname("127.0.0.1"))) perror("failed to resolve host");
     else {
        // prepare the server address
        memset((char *) &amp;addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;
        bcopy((char *)server-&gt;h_addr, (char *)&amp;addr.sin_addr.s_addr, server-&gt;h_length);
        addr.sin_port = htons(45454);
  
        // create a socket and connect to the server
        if ((sock = socket(AF_INET, SOCK_STREAM, 0)) &lt; 0) perror("failed to create client socket");
        else {
           if (connect(sock,(struct sockaddr *) &amp;addr,sizeof(addr)) &lt; 0) perror("failed to connect to server");
           else {
              printf("Connection is established will sleep now\n");
              sleep(3);
              printf("done sleeping\n");
              close(sock);
              printf("socket is closed\n");
           }
        }
     }
     return 0;
  }
  </code></pre>
  
  <p>In the present example the second call to <code>getsockopts()</code> in the server fails resulting in <code>perror("3")</code> to be called. If I however comment this line out as well as the last call to <code>setsockopts()</code> the first call to <code>getsockopts()</code> fails (which previously seemed to work).</p>
  
  <p>Any insights to where I go wrong are appreciated</p>