serv05.lc 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /* include serv05a */
  2. #include "unp.h"## 1 ##src/server/serv05.c##
  3. #include "child.h"## 2 ##src/server/serv05.c##
  4. static int nchildren;## 3 ##src/server/serv05.c##
  5. int## 4 ##src/server/serv05.c##
  6. main(int argc, char **argv)## 5 ##src/server/serv05.c##
  7. {## 6 ##src/server/serv05.c##
  8. int listenfd, i, navail, maxfd, nsel, connfd, rc;## 7 ##src/server/serv05.c##
  9. void sig_int(int);## 8 ##src/server/serv05.c##
  10. pid_t child_make(int, int, int);## 9 ##src/server/serv05.c##
  11. ssize_t n;## 10 ##src/server/serv05.c##
  12. fd_set rset, masterset;## 11 ##src/server/serv05.c##
  13. socklen_t addrlen, clilen;## 12 ##src/server/serv05.c##
  14. struct sockaddr *cliaddr;## 13 ##src/server/serv05.c##
  15. if (argc == 3)## 14 ##src/server/serv05.c##
  16. listenfd = Tcp_listen(NULL, argv[1], &addrlen);## 15 ##src/server/serv05.c##
  17. else if (argc == 4)## 16 ##src/server/serv05.c##
  18. listenfd = Tcp_listen(argv[1], argv[2], &addrlen);## 17 ##src/server/serv05.c##
  19. else## 18 ##src/server/serv05.c##
  20. err_quit("usage: serv05 [ <host> ] <port#> <#children>");## 19 ##src/server/serv05.c##
  21. FD_ZERO(&masterset);## 20 ##src/server/serv05.c##
  22. FD_SET(listenfd, &masterset);## 21 ##src/server/serv05.c##
  23. maxfd = listenfd;## 22 ##src/server/serv05.c##
  24. cliaddr = Malloc(addrlen);## 23 ##src/server/serv05.c##
  25. nchildren = atoi(argv[argc - 1]);## 24 ##src/server/serv05.c##
  26. navail = nchildren;## 25 ##src/server/serv05.c##
  27. cptr = Calloc(nchildren, sizeof(Child));## 26 ##src/server/serv05.c##
  28. /* 4prefork all the children */## 27 ##src/server/serv05.c##
  29. for (i = 0; i < nchildren; i++) {## 28 ##src/server/serv05.c##
  30. child_make(i, listenfd, addrlen); /* parent returns */## 29 ##src/server/serv05.c##
  31. FD_SET(cptr[i].child_pipefd, &masterset);## 30 ##src/server/serv05.c##
  32. maxfd = max(maxfd, cptr[i].child_pipefd);## 31 ##src/server/serv05.c##
  33. }## 32 ##src/server/serv05.c##
  34. Signal(SIGINT, sig_int);## 33 ##src/server/serv05.c##
  35. for (;;) {## 34 ##src/server/serv05.c##
  36. rset = masterset;## 35 ##src/server/serv05.c##
  37. if (navail <= 0)## 36 ##src/server/serv05.c##
  38. FD_CLR(listenfd, &rset); /* turn off if no available children */## 37 ##src/server/serv05.c##
  39. nsel = Select(maxfd + 1, &rset, NULL, NULL, NULL);## 38 ##src/server/serv05.c##
  40. /* 4check for new connections */## 39 ##src/server/serv05.c##
  41. if (FD_ISSET(listenfd, &rset)) {## 40 ##src/server/serv05.c##
  42. clilen = addrlen;## 41 ##src/server/serv05.c##
  43. connfd = Accept(listenfd, cliaddr, &clilen);## 42 ##src/server/serv05.c##
  44. for (i = 0; i < nchildren; i++)## 43 ##src/server/serv05.c##
  45. if (cptr[i].child_status == 0)## 44 ##src/server/serv05.c##
  46. break; /* available */## 45 ##src/server/serv05.c##
  47. if (i == nchildren)## 46 ##src/server/serv05.c##
  48. err_quit("no available children");## 47 ##src/server/serv05.c##
  49. cptr[i].child_status = 1; /* mark child as busy */## 48 ##src/server/serv05.c##
  50. cptr[i].child_count++;## 49 ##src/server/serv05.c##
  51. navail--;## 50 ##src/server/serv05.c##
  52. n = Write_fd(cptr[i].child_pipefd, "", 1, connfd);## 51 ##src/server/serv05.c##
  53. Close(connfd);## 52 ##src/server/serv05.c##
  54. if (--nsel == 0)## 53 ##src/server/serv05.c##
  55. continue; /* all done with select() results */## 54 ##src/server/serv05.c##
  56. }## 55 ##src/server/serv05.c##
  57. /* 4find any newly-available children */## 56 ##src/server/serv05.c##
  58. for (i = 0; i < nchildren; i++) {## 57 ##src/server/serv05.c##
  59. if (FD_ISSET(cptr[i].child_pipefd, &rset)) {## 58 ##src/server/serv05.c##
  60. if ((n = Read(cptr[i].child_pipefd, &rc, 1)) == 0)## 59 ##src/server/serv05.c##
  61. err_quit("child %d terminated unexpectedly", i);## 60 ##src/server/serv05.c##
  62. cptr[i].child_status = 0;## 61 ##src/server/serv05.c##
  63. navail++;## 62 ##src/server/serv05.c##
  64. if (--nsel == 0)## 63 ##src/server/serv05.c##
  65. break; /* all done with select() results */## 64 ##src/server/serv05.c##
  66. }## 65 ##src/server/serv05.c##
  67. }## 66 ##src/server/serv05.c##
  68. }## 67 ##src/server/serv05.c##
  69. }## 68 ##src/server/serv05.c##
  70. /* end serv05a */
  71. void## 69 ##src/server/serv05.c##
  72. sig_int(int signo)## 70 ##src/server/serv05.c##
  73. {## 71 ##src/server/serv05.c##
  74. int i;## 72 ##src/server/serv05.c##
  75. void pr_cpu_time(void);## 73 ##src/server/serv05.c##
  76. /* 4terminate all children */## 74 ##src/server/serv05.c##
  77. for (i = 0; i < nchildren; i++)## 75 ##src/server/serv05.c##
  78. kill(cptr[i].child_pid, SIGTERM);## 76 ##src/server/serv05.c##
  79. while (wait(NULL) > 0) /* wait for all children */## 77 ##src/server/serv05.c##
  80. ;## 78 ##src/server/serv05.c##
  81. if (errno != ECHILD)## 79 ##src/server/serv05.c##
  82. err_sys("wait error");## 80 ##src/server/serv05.c##
  83. pr_cpu_time();## 81 ##src/server/serv05.c##
  84. for (i = 0; i < nchildren; i++)## 82 ##src/server/serv05.c##
  85. printf("child %d, %ld connections\n", i, cptr[i].child_count);## 83 ##src/server/serv05.c##
  86. exit(0);## 84 ##src/server/serv05.c##
  87. }## 85 ##src/server/serv05.c##