12.22

#include "csapp.h"

/* read line from connfd and echo line to connfd */
int echo_line(int connfd);

void command(void);

int main(int argc, char **argv)
{
  int listenfd, connfd;
  socklen_t clientlen;
  struct sockaddr_storage clientaddr;
  fd_set read_set, ready_set;

  if (argc != 2) {
    fprintf(stderr, "usage: %s <port>\nuse port 5000 here\n", argv[0]);
    // default port 5000
    listenfd = Open_listenfd("5000");
  } else {
    listenfd = Open_listenfd(argv[1]);  //line:conc:select:openlistenfd
  }

  FD_ZERO(&read_set);              /* Clear read set */ //line:conc:select:clearreadset
  FD_SET(STDIN_FILENO, &read_set); /* Add stdin to read set */ //line:conc:select:addstdin
  FD_SET(listenfd, &read_set);     /* Add listenfd to read set */ //line:conc:select:addlistenfd

  // max n for select
  int n = listenfd+1;

  while (1) {
    ready_set = read_set;
    Select(n, &ready_set, NULL, NULL, NULL); //line:conc:select:select

    if (FD_ISSET(STDIN_FILENO, &ready_set)) //line:conc:select:stdinready
      command(); /* Read command line from stdin */

    if (FD_ISSET(listenfd, &ready_set)) { //line:conc:select:listenfdready
      clientlen = sizeof(struct sockaddr_storage);
      connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);


      // listen to accepted io ports
      if (connfd+1 > FD_SETSIZE) {
        fprintf(stderr, "too many clients\n");
        Close(connfd);
      }
      n = n > connfd+1 ? n : connfd+1;
      FD_SET(connfd, &read_set);
    }

    // echo one line every time
    int fd;
    for (fd = listenfd+1; fd < n; fd++)
      if (FD_ISSET(fd, &ready_set))
        if (echo_line(fd) == -1) {
          Close(fd);
          FD_CLR(fd, &read_set);
        }
  }
}

void command(void) {
  char buf[MAXLINE];
  if (!Fgets(buf, MAXLINE, stdin))
    exit(0); /* EOF */
  printf("%s", buf); /* Process the input command */
}

int echo_line(int connfd) {
  ssize_t n;
  char buf[1];

  while ((n = Rio_readn(connfd, buf, 1)) > 0) {
    Rio_writen(connfd, buf, n);
    if (buf[0] = '\n')
      return 0;
  }
  return -1;
}

run server

(cd ./site/content/chapter12/code; make && ./12.22 5000)

input command in terminal or telnet to test server

telnet 127.0.0.1 5000
comments powered by Disqus