title: poll() socket programming tcp linux multiple connections issue
body: <p>I'm new to socket programming, but I have followed ibm example at <a href="https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_71/rzab6/poll.htm" rel="nofollow">https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_71/rzab6/poll.htm</a> and changed some code to make it better but when I connect to the server via telnet ip port, and make it echo messages it works for the first client that connects but on second it does not echo the messages?</p>
  
  <pre><code>#include &lt;netinet/in.h&gt; // sockaddr_in struct
  #include &lt;arpa/inet.h&gt; //inet_addr()
  #include &lt;sys/socket.h&gt;
  #include &lt;errno.h&gt; //errors
  #include &lt;stdio.h&gt; //perror()
  #include &lt;cstdlib&gt; //EXIT_FAILURE
  #include &lt;sys/ioctl.h&gt; //FIONBIO
  #include &lt;unistd.h&gt; //close file descriptor
  #include &lt;fcntl.h&gt; //make non blocking
  #include &lt;poll.h&gt; //poll stuff
  #include &lt;string.h&gt; //memset
  int main()
  {
      int s = -1;
      int rc;
      int optval = 1;
      int timeout;
      bool end_server = false; //because we need to log if EWOULDBLOCK is true...
  
      struct pollfd fds[200]; //initialize pollfd struct
      int nfds = 1; // nfds_t really set to 1 else it will be 199 once we pass it to poll....
  
      int current_size = 0;
  
      int new_s = -1;
  
      int close_conn;
  
      char *buff;
  
      int len;
  
      bool compress_array;
  
      s = socket(AF_INET, SOCK_STREAM, 0);
  
      //make socket description reusable with SO_REUSEADDR
      rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast&lt;char*&gt;(&amp;optval), sizeof(optval));
      if(rc &lt; 0){
          perror("setsockopt()");
          close(s);
          exit(EXIT_FAILURE);
      }
  
      //make socket non-blocking
      //rc = ioctl(s, FIONBIO, reinterpret_cast&lt;char*&gt;(&amp;optval));
      //if(rc &lt; 0)
      //{
      //    perror("ioctl()");
      //    close(s);
      //    exit(EXIT_FAILURE);
      //}
      fcntl(s, F_SETFL, O_NONBLOCK);
  
      struct sockaddr_in saddr;
      //initialize sockaddr_in struct
      memset(&amp;saddr, 0, sizeof(saddr));
  
      saddr.sin_family = AF_INET;
      saddr.sin_port = htons(80);
      saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
  
      rc = bind(s, reinterpret_cast&lt;struct sockaddr *&gt;(&amp;saddr), sizeof(saddr));
  
      if(rc &lt; 0){
          perror("bind()");
          exit(EXIT_FAILURE);
      }
  
      rc = listen(s, 32);
      if(rc &lt; 0){
          perror("listen() failed");
          close(s);
          exit(EXIT_FAILURE);
      }
  
      //initialize fds struct
      memset(&amp;fds, 0, sizeof(fds));
  
      fds[0].fd = s;
      fds[0].events = POLLIN; //check if data to read
  
      //initialize timeout value to 3 mins based on millisecs
      //timeout = (3 * 60 * 1000); // because function will be like sleep() that uses millisecs
      timeout = 10000;
  
      do{
          //call poll() and wait 3 mins to complete because of timeout
          printf("Waiting on poll()...\n");
          rc = poll(fds, nfds, timeout);
  
          if(rc &lt; 0){
              perror("poll() failed");
              exit(EXIT_FAILURE);
          }
  
          //check if 3 minutes timeout expired
          if(rc == 0){
              printf("poll() timed out ending program...\n");
              exit(EXIT_FAILURE);
          }
  
          current_size = nfds;
          for(int i = 0; i &lt; current_size; i++)
          {
              //loop thru fds and check if revents returns POLLIN, means the fd have data to read...
              if(fds[i].revents == 0)
                  continue;
  
  
              //if revents is not POLLIN then exit program and log
              if(fds[i].revents != POLLIN){
                  printf("revents != POLLIN, revents = %d\n", fds[i].revents);
                  //end_server = true;
                  //break;
                  //perror("revents unknown");
                  //exit(EXIT_FAILURE);
                  close(fds[i].fd);
                  fds[i].fd = -1;
                  break;
              }
  
              if(fds[i].fd == s){
                  printf("Listening socket available\n");
  
                  do{
                      //accept each new incoming connections
                      new_s = accept(s, NULL, NULL);
                      if(new_s &lt; 0){
                          if(errno != EWOULDBLOCK){
                              perror("accept() failed because of socket would block");
                              end_server = true;
                          }
                          //printf("something else wrong with accept()\n");
                          break;
                      }
  
                      //add new incoming connection
                      printf("new incoming connection - nfds: %d\n", new_s);
                      fds[nfds].fd = new_s;
                      fds[nfds].events = POLLIN;
                      nfds++;
                      //continue;
                      //loop back up and accept another connection
  
                  } while(new_s != -1);
              }
              // file descriptor is readable because its now new_s instead of s
              else {
                  printf("descriptor %d is readable\n", fds[i].fd);
                  close_conn = false;
                  //receive all data on this connection till we go back and poll again
                  do {
  
                      rc = recv(fds[i].fd, reinterpret_cast&lt;void*&gt;(&amp;buff), sizeof(buff), 0);
                      if(rc &lt; 0){
                          if(errno != EWOULDBLOCK){
                              perror("recv() failed");
                              close_conn = true;
                          }
                          break;
                      }
  
                      //check if conn was closed by client
                      if(rc == 0){
                          printf("connection closed");
                          close_conn = true;
                          break;
                      }
  
                      //data was received
                      len = rc;
                      printf("%d bytes received", len);
  
                      //process stuff or echo data back to client
                      rc = send(fds[i].fd, reinterpret_cast&lt;void*&gt;(&amp;buff), sizeof(buff), 0);
                      if(rc &lt; 0){
                          perror("send() failed");
                          close_conn = true;
                          break;
                      }
                      memset(&amp;buff, 0, sizeof(buff));
  
                  } while (true);
                  if(close_conn){
                      close(fds[i].fd);
                      fds[i].fd = -1;
                      compress_array = true;
                  }
  
              }
  
  
          }
          if(compress_array){
              compress_array = false;
              int i = 0;
              for(i = 0; i &lt; nfds; i++){
                  if(fds[i].fd == -1){
                      for(int j = i; j &lt; nfds; j++){
                          fds[j].fd = fds[j+1].fd;
                      }
                      i--;
                      nfds--;
                  }
              }
          }
  
      } while (end_server == false);
  
      //clean all sockets that are open
      for(int i = 0; i &lt; nfds; i++){
          if(fds[i].fd &gt; 0){ // if already -1 don't need to close socket
              close(fds[i].fd);
              fds[i].fd = -1;
          }
      }
  
  
  
      return 0;
  }
  </code></pre>