I am a little bit confused in a socket example through select()

Hi, I am a newbie about network programming. All codes come from this book: UNIX Network Programming Volume 1, Third Edition.

It is a TCP server by use select()

  int main(int argc, char **argv) {
      int                    i, maxi, maxfd, listenfd, connfd, sockfd;
      int                    nready, client[FD_SETSIZE];
      ssize_t                n;
      fd_set                rset, allset;
      char                buf[MAXLINE];
      socklen_t            clilen;
      struct sockaddr_in    cliaddr, servaddr;
  
      listenfd = Socket(AF_INET, SOCK_STREAM, 0);
  
      bzero(&servaddr, sizeof(servaddr));
      servaddr.sin_family      = AF_INET;
      servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
      servaddr.sin_port        = htons(SERV_PORT);
  
      Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
  
      Listen(listenfd, LISTENQ);
  
      maxfd = listenfd;            /* initialize */
      maxi = -1;                    /* index into client[] array */
      for (i = 0; i < FD_SETSIZE; i++)
          client = -1;            /* -1 indicates available entry */
      FD_ZERO(&allset);
      FD_SET(listenfd, &allset);
  
      for ( ; ; ) {
          rset = allset;        /* structure assignment */
          nready = Select(maxfd+1, &rset, NULL, NULL, NULL);
  
          if (FD_ISSET(listenfd, &rset)) {    /* new client connection */
              clilen = sizeof(cliaddr);
              connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
  
              for (i = 0; i < FD_SETSIZE; i++)
                  if (client < 0) {
                      client = connfd;    /* save descriptor */
                      break;
                  }
              if (i == FD_SETSIZE)
                  err_quit("too many clients");
  
              FD_SET(connfd, &allset);    /* add new descriptor to set */
              if (connfd > maxfd)
                  maxfd = connfd;            /* for select */
              if (i > maxi)
                  maxi = i;                /* max index in client[] array */
  
              if (--nready <= 0)
                  continue;                /* no more readable descriptors */
          }
  
          for (i = 0; i <= maxi; i++) {    /* check all clients for data */
              if ( (sockfd = client) < 0)
                  continue;
              if (FD_ISSET(sockfd, &rset)) {
                if ( (n = Read(sockfd, buf, MAXLINE)) == 0) {
                        /*4connection closed by client */
                    Close(sockfd);
                    FD_CLR(sockfd, &allset);
                    client = -1;
                } else
                    Writen(sockfd, buf, n);
  
                  if (--nready <= 0)
                      break;                /* no more readable descriptors */
              }
          }
      }
  }
  

Please focus on the highlighted section, There are Read(), Writen() functions, the context of them are shown below:

  ssize_t Read(int fd, void *ptr, size_t nbytes) {
      ssize_t        n;
      if ( (n = read(fd, ptr, nbytes)) == -1)
          err_sys("read error");
      return(n);
  }
  
  void Writen(int fd, void *ptr, size_t nbytes) {
      if (writen(fd, ptr, nbytes) != nbytes)
          err_sys("writen error");
  }
  
  void err_sys(const char *fmt, ...) {
      va_list        ap;
      va_start(ap, fmt);
      err_doit(1, LOG_ERR, fmt, ap);
      va_end(ap);
      exit(1);
  }
  

Why the TCP server once received a read error [the Read() function has exit()], then exit the program? It will happen when a client is sending data and shutdown abnormally.
The same problem with writen().

Is it possible to change the codes like this? Then any disadvantage about modified codes?

              if (FD_ISSET(sockfd, &rset)) {
                if ( (n = Read(sockfd, buf, MAXLINE)) <= 0) {
                        /*4connection closed by client */
                      if ( n == 0 ) {
                       puts( "Client hung up!" );
                    } else {
                       puts( "Read error!" );
                    }
                    Close the socket when error or hung up.
                    Close(sockfd);
                    FD_CLR(sockfd, &allset);
                    client = -1;
                } else
                    Writen(sockfd, buf, n);
  
  ssize_t Read(int fd, void *ptr, size_t nbytes) {
       ssize_t        n;
       if ( (n = read(fd, ptr, nbytes)) == -1)
           puts("read error");
       return(n);
   }
   
   void Writen(int fd, void *ptr, size_t nbytes) {
       if (writen(fd, ptr, nbytes) != nbytes)
           puts("writen error");
   }
  

Thank you for your help!

To be honest, I do not really understand your question.
What exactly is the problem?

Just a quick thing about your code changes: They would not change anything except for the puts().
read() returns either -1 on error or the number of bytes read. The -1 case will call err_sys which will exit the whole program. So Read() will always return something >= 0

Hi, I hope the TCP server never stop or exit anytime. In the original one, the TCP server exits once any read error occur, it is horrible since clients may hung up during the transmission and it is nondeterministic.
So I change a little bit about the codes and deduct exit() functions. However, I am not sure whether these changes affect select() method or not. So it is the question I want to ask.

Thanks.