serv05.c 2.4 KB

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