title: Socket programming for multi-clients with 'select()' in C
body: <p>This is a question about socket programming for multi-client.</p>
  
  <p>While I was thinking how to make my single client and server program 
  to multi clients,I encountered how to implement this.
  But even if I was searching for everything, kind of confusion exists.</p>
  
  <ol>
  <li><p>I was thinking to implement with select(), because it is less heavy than fork.
  but I have much global variables not to be shared, so I hadn`t considered thread to use.</p></li>
  <li><p>and so to use select(), I could have the general knowledge about FD_functions to utilize, but here I have my question, because generally in the examples on websites, it only shows multi-client server program...</p></li>
  </ol>
  
  <p>Since I use sequential recv() and send() in client and also in server program
  that work really well when it`s single client and server, but
  I have no idea about how it must be changed for multi cilent.
  Does the client also must be unblocking?
  What are all requirements for select()?</p>
  
  <p>The things I did on my server program to be multi-client</p>
  
  <p>1) I set my socket option for reuse address, with SO_REUSEADDR</p>
  
  <p>2) and set my server as non-blocking mode with O_NONBLOCK using fctl().</p>
  
  <p>3) and put the timeout argument as zero.</p>
  
  <p>and proper use of FD_functions after above.</p>
  
  <p>But when I run my client program one and many more, from the second client,
  client program blocks, not getting accepted by server.</p>
  
  <p>I guess the reason is because I put my server program`s main function part 
  into the 'recv was >0 ' case.</p>
  
  <p>for example with my server code,</p>
  
  <p>(I`m using temp and read as fd_set, and read as master in this case)</p>
  
  <pre><code>int main(void)
  {
  
    int conn_sock, listen_sock;
    struct sockaddr_in s_addr, c_addr;
    int rq, ack;
    char path[100];
    int pre, change, c;
    int conn, page_num, x;
    int c_len = sizeof(c_addr);
    int fd;
    int flags;
    int opt = 1;
    int nbytes;
    fd_set read, temp;
  
    if ((listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) &lt; 0)
    {
      perror("socket error!");
      return 1;
    }
  
    memset(&amp;s_addr, 0, sizeof(s_addr));
  
    s_addr.sin_family = AF_INET;
    s_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    s_addr.sin_port = htons(3500);
    if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &amp;opt, sizeof(int)) == -1)
    {
  
      perror("Server-setsockopt() error ");
      exit(1);
  
    }
    flags = fcntl(listen_sock, F_GETFL, 0);
    fcntl(listen_sock, F_SETFL, flags | O_NONBLOCK);
  
    //fcntl(listen_sock, F_SETOWN, getpid());
  
    bind(listen_sock, (struct sockaddr*) &amp;s_addr, sizeof(s_addr));
  
    listen(listen_sock, 8);
  
    FD_ZERO(&amp;read);
    FD_ZERO(&amp;temp);
  
    FD_SET(listen_sock, &amp;read);
    while (1)
    {
  
      temp = read;
  
      if (select(FD_SETSIZE, &amp;temp, (fd_set *) 0, (fd_set *) 0,
          (struct timeval *) 0) &lt; 1)
      {
        perror("select error:");
        exit(1);
      }
  
      for (fd = 0; fd &lt; FD_SETSIZE; fd++)
      {
        //CHECK all file descriptors
  
        if (FD_ISSET(fd, &amp;temp))
        {
  
          if (fd == listen_sock)
          {
  
            conn_sock = accept(listen_sock, (struct sockaddr *) &amp;c_addr, &amp;c_len);
            FD_SET(conn_sock, &amp;read);
            printf("new client got session: %d\n", conn_sock);
  
          }
          else
          {
  
            nbytes = recv(fd, &amp;conn, 4, 0);
            if (nbytes &lt;= 0)
            {
              close(fd);
              FD_CLR(fd, &amp;read);
            }
            else
            {
  
              if (conn == Session_Rq)
              {
  
                ack = Session_Ack;
                send(fd, &amp;ack, sizeof(ack), 0);
  
                root_setting();
  
                c = 0;
                while (1)
                {
                  c++;
                  printf("in while loop\n");
                  recv(fd, &amp;page_num, 4, 0);
  
                  if (c &gt; 1)
                  {
                    change = compare_with_pre_page(pre, page_num);
  
                    if (change == 1)
                    {
                      page_stack[stack_count] = page_num;
                      stack_count++;
                    }
                    else
                    {
                      printf("same as before page\n");
                    }
                  } //end of if
                  else if (c == 1)
                  {
                    page_stack[stack_count] = page_num;
                    stack_count++;
                  }
  
                  printf("stack count:%d\n", stack_count);
                  printf("in page stack: &lt;");
  
                  for (x = 0; x &lt; stack_count; x++)
                  {
                    printf(" %d ", page_stack[x]);
                  }
  
                  printf("&gt;\n");
  
                  rq_handler(fd);
  
                  if (logged_in == 1)
                  {
                    printf("You are logged in state now, user: %s\n",
                        curr_user.ID);
                  }
                  else
                  {
                    printf("not logged in.\n");
                    c = 0;
                  }
  
                  pre = page_num;
                } //end of while
              } //end of if
            }
          } //end of else
        } //end of fd_isset
      } //end of for loop  
    } //end of outermost while
  }
  </code></pre>
  
  <p>if needed for code explanation : What I was about to work of this code was,
  to make kind of web pages to implement 'browser' for server.
  I wanted to make every client get session for server to get login-page or so.</p>
  
  <p>But the execution result is, as I told above.
  Why is that?</p>
  
  <ol>
  <li><p>the socket in the client program must be non-blocking mode too
  to be used with non-blocking Server program to use select()?</p></li>
  <li><p>Or should I use fork or thread to make multi client and manage with select?
  The reason I say this is, after I considered a lot about this problem,
  'select()' seems only proper for multi client chatting program... that many 
  'forked' or 'threaded' clients can pend to, in such as chat room.
  how do you think?...
  Is select also possible or proper thing to use for normal multi-client program?</p></li>
  </ol>
  
  <p>If there something I missed to let my multi client program work fine,
  please give me some knowledge of yours or some requirements for the proper use of select.
  I didn`t know multi-client communication was not this much easy before :)
  I also considered to use epoll but I think I need to understand first about select well.</p>
  
  <p>Thanks for reading.</p>