title: Simple socket non-blocking I/O
body: <p>I am trying have non-blocking I/O between a server and client. After the two are connected, I am trying to use fork to handle the IO, but the server side gets an error when trying to read of "Transport endpoint is not connected" and it happens twice (because of fork I'm guessing?). </p>
  
  <p>Server code</p>
  
  <pre><code>//includes taken out
  
  #define PORT "4950"
  #define STDIN 0
  
  struct sockaddr name;
  
  void set_nonblock(int socket) {
      int flags;
      flags = fcntl(socket,F_GETFL,0);
      assert(flags != -1);
      fcntl(socket, F_SETFL, flags | O_NONBLOCK);
  }
  
  
  // get sockaddr, IPv4 or IPv6:
  void *get_in_addr(struct sockaddr *sa) {
      if (sa-&gt;sa_family == AF_INET)
          return &amp;(((struct sockaddr_in*)sa)-&gt;sin_addr);
  
      return &amp;(((struct sockaddr_in6*)sa)-&gt;sin6_addr);
  }
  
  
  int main(int agrc, char** argv) {
      int status, sock, adrlen, new_sd;
  
      struct addrinfo hints;
      struct addrinfo *servinfo;  //will point to the results
  
      //store the connecting address and size
      struct sockaddr_storage their_addr;
      socklen_t their_addr_size;
  
      //socket infoS
      memset(&amp;hints, 0, sizeof hints); //make sure the struct is empty
      hints.ai_family = AF_INET;
      hints.ai_socktype = SOCK_STREAM; //tcp
      hints.ai_flags = AI_PASSIVE;     //use local-host address
  
      //get server info, put into servinfo
      if ((status = getaddrinfo("127.0.0.1", PORT, &amp;hints, &amp;servinfo)) != 0) {
          fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
          exit(1);
      }
  
      //make socket
      sock = socket(servinfo-&gt;ai_family, servinfo-&gt;ai_socktype, servinfo-&gt;ai_protocol);
      if (sock &lt; 0) {
          printf("\nserver socket failure %m", errno);
          exit(1);
      }
  
      //allow reuse of port
      int yes=1;
      if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&amp;yes,sizeof(int)) == -1) {
          perror("setsockopt");
          exit(1);
      }
  
      //unlink and bind
      unlink("127.0.0.1");
      if(bind (sock, servinfo-&gt;ai_addr, servinfo-&gt;ai_addrlen) &lt; 0) {
          printf("\nBind error %m", errno);
          exit(1);
      }
  
      freeaddrinfo(servinfo);
  
      //listen
      if(listen(sock, 5) &lt; 0) {
          printf("\nListen error %m", errno);
          exit(1);
      } 
      their_addr_size = sizeof(their_addr);
      //accept
      new_sd = accept(sock, (struct sockaddr*)&amp;their_addr, &amp;their_addr_size);
      if( new_sd &lt; 0) {
          printf("\nAccept error %m", errno);
          exit(1);
      }
  
      cout&lt;&lt;"\nSuccessful Connection!";
  
      //set nonblock
      set_nonblock(new_sd);
  
      char* in = new char[255];
      char* out = new char[255];
      int numSent;
      int numRead;
      pid_t pid;
  
      fork();
      pid = getpid();
  
      if(pid == 0) {
  
          while( !(out[0] == 'q' &amp;&amp; out[1] == 'u' &amp;&amp; out[2] == 'i' &amp;&amp; out[3] == 't') ) {
  
              fgets(out, 255, stdin);
              numSent = send(sock, out, strlen(out), 0);
  
              if(numSent &lt; 0) {
                  printf("\nError sending %m", errno);
                  exit(1);
              }   //end error
          }   //end while
      }   //end child
  
      else {
          numRead = recv(sock, in, 255, 0);
          if(numRead &lt; 0) {
              printf("\nError reading %m", errno);
              exit(1);
          }   //end error
          else {
              cout&lt;&lt;in;
              for(int i=0;i&lt;255;i++)
                  in[i] = '\0';
  
          }   //end else
      }   //end parent
  
      cout&lt;&lt;"\n\nExiting normally\n";
      return 0;
  }
  </code></pre>
  
  <p>Client code</p>
  
  <p>//includes taken out</p>
  
  <pre><code>#define PORT "4950"
  
  struct sockaddr name;
  
  void set_nonblock(int socket) {
      int flags;
      flags = fcntl(socket,F_GETFL,0);
      assert(flags != -1);
      fcntl(socket, F_SETFL, flags | O_NONBLOCK);
  }
  
  
  // get sockaddr, IPv4 or IPv6:
  void *get_in_addr(struct sockaddr *sa) {
      if (sa-&gt;sa_family == AF_INET)
          return &amp;(((struct sockaddr_in*)sa)-&gt;sin_addr);
  
      return &amp;(((struct sockaddr_in6*)sa)-&gt;sin6_addr);
  }
  
  int main(int agrc, char** argv) {
      int status, sock, adrlen;
  
      struct addrinfo hints;
      struct addrinfo *servinfo;  //will point to the results
  
      memset(&amp;hints, 0, sizeof hints); //make sure the struct is empty
      hints.ai_family = AF_INET;
      hints.ai_socktype = SOCK_STREAM; //tcp
      hints.ai_flags = AI_PASSIVE;     //use local-host address
  
      //get server info, put into servinfo
      if ((status = getaddrinfo("127.0.0.1", PORT, &amp;hints, &amp;servinfo)) != 0) {
          fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
          exit(1);
      }
  
      //make socket
      sock = socket(servinfo-&gt;ai_family, servinfo-&gt;ai_socktype, servinfo-&gt;ai_protocol);
      if (sock &lt; 0) {
          printf("\nserver socket failure %m", errno);
          exit(1);
      }
  
      if(connect(sock, servinfo-&gt;ai_addr, servinfo-&gt;ai_addrlen) &lt; 0) {
          printf("\nclient connection failure %m", errno);
          exit(1);
      }
  
      cout&lt;&lt;"\nSuccessful connection!";
  
      //set nonblock
      set_nonblock(sock);
  
      char* out = new char[255];
      char* in = new char[255];
      int numRead;
      int numSent;
      pid_t pid;
  
      fork();
      pid = getpid();
  
      if(pid == 0) {
  
          while( !(out[0] == 'q' &amp;&amp; out[1] == 'u' &amp;&amp; out[2] == 'i' &amp;&amp; out[3] == 't') ) {
  
              fgets(out, 255, stdin);
              numSent = send(sock, out, strlen(out), 0);
  
              if(numSent &lt; 0) {
                  printf("\nError sending %m", errno);
                  exit(1);
              }   //end error
          }   //end while
      }   //end child process
  
      else {
          while( !(in[0] == 'q' &amp;&amp; in[1] == 'u' &amp;&amp; in[2] == 'i' &amp;&amp; in[3] == 't') ) {
          numRead = recv(sock, in, 255, 0);
              cout&lt;&lt;in;
              for(int i=0;i&lt;255;i++)
                  in[i] = '\0';
          }
      }   //end parent process
  
      cout&lt;&lt;"\n\nExiting normally\n";
      return 0;
  }
  </code></pre>
  
  <p>I also tried using threads to do the I/O. The problem there is that when I run the program, its like the threads don't occur. The program just runs with a "Successful Connection" and then "exiting normally." I put some cout statements into the while(1) loops and they did print out a few times, but they just stop for some reason. I'm not sure if its a problem with my threads or my sockets. The code (very similar to above) for that is here - </p>
  
  <p>Server</p>
  
  <pre><code>//includes taken out
  
  #define PORT "4950"
  #define STDIN 0
  
  pthread_t readthread;
  pthread_t sendthread;
  
  char* in = new char[255];
  char* out = new char[255];
  int numSent;
  int numRead;
  
  struct sockaddr name;
  int sock, new_sd;
  
  void* readThread(void* threadid) {
  
      while(1) {
  
          numRead = recv(new_sd, in, 255, 0);
  
          if(numRead &gt; 0) {
              cout&lt;&lt;"\n"&lt;&lt;in;
              for(int i=0;i&lt;strlen(in);i++)
                  in[i] = '\0';
          }   //end if
          else if(numRead &lt; 0) {
              printf("\nError reading %m", errno);
              exit(1);
          }
  
      }   //end while
  }   //END READTHREAD
  
  
  void* sendThread(void* threadid) {
  
       while(1) {
  
          cin.getline(out, 255);
  
          numSent = send(new_sd, out, 255, 0);
  
          if(numSent &gt; 0) {
              for(int i=0;i&lt;strlen(out);i++)
                  out[i] = '\0';
          }   //end if
          else if(numSent &lt; 0) {
              printf("\nError sending %m", errno);
              exit(1);
          }
      }   //end while
  }   //END SENDTHREAD
  
  void set_nonblock(int socket) {
      int flags;
      flags = fcntl(socket,F_GETFL,0);
      assert(flags != -1);
      fcntl(socket, F_SETFL, flags | O_NONBLOCK);
  }
  
  // get sockaddr, IPv4 or IPv6:
  void *get_in_addr(struct sockaddr *sa) {
      if (sa-&gt;sa_family == AF_INET)
          return &amp;(((struct sockaddr_in*)sa)-&gt;sin_addr);
  
      return &amp;(((struct sockaddr_in6*)sa)-&gt;sin6_addr);
  }
  
  int main(int agrc, char** argv) {
      int status, adrlen;
  
      struct addrinfo hints;
      struct addrinfo *servinfo;  //will point to the results
  
      //store the connecting address and size
      struct sockaddr_storage their_addr;
      socklen_t their_addr_size;
  
      //socket infoS
      memset(&amp;hints, 0, sizeof hints); //make sure the struct is empty
      hints.ai_family = AF_INET;
      hints.ai_socktype = SOCK_STREAM; //tcp
      hints.ai_flags = AI_PASSIVE;     //use local-host address
  
      //get server info, put into servinfo
      if ((status = getaddrinfo("127.0.0.1", PORT, &amp;hints, &amp;servinfo)) != 0) {
          fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
          exit(1);
      }
  
      //make socket
      sock = socket(servinfo-&gt;ai_family, servinfo-&gt;ai_socktype, servinfo-&gt;ai_protocol);
      if (sock &lt; 0) {
          printf("\nserver socket failure %m", errno);
          exit(1);
      }
  
      //allow reuse of port
      int yes=1;
      if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&amp;yes,sizeof(int)) == -1) {
          perror("setsockopt");
          exit(1);
      }
  
      //unlink and bind
      unlink("127.0.0.1");
      if(bind (sock, servinfo-&gt;ai_addr, servinfo-&gt;ai_addrlen) &lt; 0) {
          printf("\nBind error %m", errno);
          exit(1);
      }
  
      freeaddrinfo(servinfo);
  
      //listen
      if(listen(sock, 5) &lt; 0) {
          printf("\nListen error %m", errno);
          exit(1);
      }
  
      their_addr_size = sizeof(their_addr);
      //accept
      new_sd = accept(sock, (struct sockaddr*)&amp;their_addr, &amp;their_addr_size);
      if( new_sd &lt; 0) {
          printf("\nAccept error %m", errno);
          exit(1);
      }  
  
      cout&lt;&lt;"\nSuccessful Connection!";
  
      //set nonblock
      set_nonblock(new_sd);
  
      pthread_attr_t attr;
      pthread_attr_init(&amp;attr);
      pthread_attr_setdetachstate(&amp;attr, PTHREAD_CREATE_JOINABLE);
  
      pthread_create(&amp;readthread, &amp;attr, readThread, (void*)0);
      pthread_create(&amp;sendthread, &amp;attr, sendThread, (void*)1);
  
      cout&lt;&lt;"\n\nExiting normally\n";
      return 0;
  }
  </code></pre>
  
  <p>Client</p>
  
  <pre><code>#define PORT "4950"
  
  pthread_t readthread;
  pthread_t sendthread;
  char* in = new char[255];
  char* out = new char[255];
  int numSent;
  int numRead;
  struct sockaddr name;
  int sock;
  
  void* readThread(void* threadid) {
  
      while(1) {
  
          numRead = recv(sock, in, 255, 0);
  
          if(numRead &gt; 0) {
              cout&lt;&lt;"\n"&lt;&lt;in;
              for(int i=0;i&lt;strlen(in);i++)
                  in[i] = '\0';
          }   //end if
          else if(numRead &lt; 0) {
              printf("\nError reading %m", errno);
              exit(1);
          }
      }   //end while
  }   //END READTHREAD
  
  void* sendThread(void* threadid) {
  
      while(1) {
  
          cin.getline(out, 255);
          numSent = send(sock, out, 255, 0);
  
          if(numSent &gt; 0) {
              for(int i=0;i&lt;strlen(out);i++)
                  out[i] = '\0';
          }   //end if
          else if(numSent &lt; 0) {
              printf("\nError sending %m", errno);
              exit(1);
          }
  
      }   //end while
  }   //END SENDTHREAD
  
  void set_nonblock(int socket) {
      int flags;
      flags = fcntl(socket,F_GETFL,0);
      assert(flags != -1);
      fcntl(socket, F_SETFL, flags | O_NONBLOCK);
  }
  
  
  // get sockaddr, IPv4 or IPv6:
  void *get_in_addr(struct sockaddr *sa) {
      if (sa-&gt;sa_family == AF_INET)
          return &amp;(((struct sockaddr_in*)sa)-&gt;sin_addr);
  
      return &amp;(((struct sockaddr_in6*)sa)-&gt;sin6_addr);
  }
  
  int main(int agrc, char** argv) {
      int status, adrlen;
  
      struct addrinfo hints;
      struct addrinfo *servinfo;  //will point to the results
  
      memset(&amp;hints, 0, sizeof hints); //make sure the struct is empty
      hints.ai_family = AF_INET;
      hints.ai_socktype = SOCK_STREAM; //tcp
      hints.ai_flags = AI_PASSIVE;     //use local-host address
  
      //get server info, put into servinfo
      if ((status = getaddrinfo("127.0.0.1", PORT, &amp;hints, &amp;servinfo)) != 0) {
          fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
          exit(1);
      }
  
      //make socket
      sock = socket(servinfo-&gt;ai_family, servinfo-&gt;ai_socktype, servinfo-&gt;ai_protocol);
      if (sock &lt; 0) {
          printf("\nserver socket failure %m", errno);
          exit(1);
      }
  
      if(connect(sock, servinfo-&gt;ai_addr, servinfo-&gt;ai_addrlen) &lt; 0) {
          printf("\nclient connection failure %m", errno);
          exit(1);
      }
  
      cout&lt;&lt;"\nSuccessful connection!";
  
      //set nonblock
      set_nonblock(sock);
  
      pthread_attr_t attr;
      pthread_attr_init(&amp;attr);
      pthread_attr_setdetachstate(&amp;attr, PTHREAD_CREATE_JOINABLE);
  
      pthread_create(&amp;readthread, &amp;attr, readThread, (void*)0);
      pthread_create(&amp;sendthread, &amp;attr, sendThread, (void*)1);
  
      cout&lt;&lt;"\n\nExiting normally\n";
      return 0;
  }
  </code></pre>
  
  <p>I apologize for the long post, but I have been at this for a few days now and am not sure how to proceed. I tried using select(), but that seems like a little much for just 1 client and a server I/O. If anyone can point out what may be going wrong above or any other tips (or I'm just plain wrong about select :)) I would greatly appreciate it.</p>