web03.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #include "unpthread.h"
  2. #include <thread.h> /* Solaris threads */
  3. #define MAXFILES 20
  4. #define SERV "80" /* port number or service name */
  5. struct file {
  6. char *f_name; /* filename */
  7. char *f_host; /* hostname or IP address */
  8. int f_fd; /* descriptor */
  9. int f_flags; /* F_xxx below */
  10. pthread_t f_tid; /* thread ID */
  11. } file[MAXFILES];
  12. #define F_CONNECTING 1 /* connect() in progress */
  13. #define F_READING 2 /* connect() complete; now reading */
  14. #define F_DONE 4 /* all done */
  15. #define F_JOINED 8 /* main has pthread_join'ed */
  16. #define GET_CMD "GET %s HTTP/1.0\r\n\r\n"
  17. int nconn, nfiles, nlefttoconn, nlefttoread;
  18. int ndone; /* number of terminated threads */
  19. pthread_mutex_t ndone_mutex = PTHREAD_MUTEX_INITIALIZER;
  20. pthread_cond_t ndone_cond = PTHREAD_COND_INITIALIZER;
  21. void *do_get_read(void *);
  22. void home_page(const char *, const char *);
  23. void write_get_cmd(struct file *);
  24. int
  25. main(int argc, char **argv)
  26. {
  27. int i, maxnconn;
  28. pthread_t tid;
  29. struct file *fptr;
  30. if (argc < 5)
  31. err_quit("usage: web <#conns> <IPaddr> <homepage> file1 ...");
  32. maxnconn = atoi(argv[1]);
  33. nfiles = min(argc - 4, MAXFILES);
  34. for (i = 0; i < nfiles; i++) {
  35. file[i].f_name = argv[i + 4];
  36. file[i].f_host = argv[2];
  37. file[i].f_flags = 0;
  38. }
  39. printf("nfiles = %d\n", nfiles);
  40. home_page(argv[2], argv[3]);
  41. nlefttoread = nlefttoconn = nfiles;
  42. nconn = 0;
  43. /* include web2 */
  44. while (nlefttoread > 0) {
  45. while (nconn < maxnconn && nlefttoconn > 0) {
  46. /* 4find a file to read */
  47. for (i = 0 ; i < nfiles; i++)
  48. if (file[i].f_flags == 0)
  49. break;
  50. if (i == nfiles)
  51. err_quit("nlefttoconn = %d but nothing found", nlefttoconn);
  52. file[i].f_flags = F_CONNECTING;
  53. Pthread_create(&tid, NULL, &do_get_read, &file[i]);
  54. file[i].f_tid = tid;
  55. nconn++;
  56. nlefttoconn--;
  57. }
  58. /* 4Wait for thread to terminate */
  59. Pthread_mutex_lock(&ndone_mutex);
  60. while (ndone == 0)
  61. Pthread_cond_wait(&ndone_cond, &ndone_mutex);
  62. for (i = 0; i < nfiles; i++) {
  63. if (file[i].f_flags & F_DONE) {
  64. Pthread_join(file[i].f_tid, (void **) &fptr);
  65. if (&file[i] != fptr)
  66. err_quit("file[i] != fptr");
  67. fptr->f_flags = F_JOINED; /* clears F_DONE */
  68. ndone--;
  69. nconn--;
  70. nlefttoread--;
  71. printf("thread %d for %s done\n", fptr->f_tid, fptr->f_name);
  72. }
  73. }
  74. Pthread_mutex_unlock(&ndone_mutex);
  75. }
  76. exit(0);
  77. }
  78. /* end web2 */
  79. void *
  80. do_get_read(void *vptr)
  81. {
  82. int fd, n;
  83. char line[MAXLINE];
  84. struct file *fptr;
  85. fptr = (struct file *) vptr;
  86. fd = Tcp_connect(fptr->f_host, SERV);
  87. fptr->f_fd = fd;
  88. printf("do_get_read for %s, fd %d, thread %d\n",
  89. fptr->f_name, fd, fptr->f_tid);
  90. write_get_cmd(fptr); /* write() the GET command */
  91. /* 4Read server's reply */
  92. for ( ; ; ) {
  93. if ( (n = Read(fd, line, MAXLINE)) == 0)
  94. break; /* server closed connection */
  95. printf("read %d bytes from %s\n", n, fptr->f_name);
  96. }
  97. printf("end-of-file on %s\n", fptr->f_name);
  98. Close(fd);
  99. fptr->f_flags = F_DONE; /* clears F_READING */
  100. Pthread_mutex_lock(&ndone_mutex);
  101. ndone++;
  102. Pthread_cond_signal(&ndone_cond);
  103. Pthread_mutex_unlock(&ndone_mutex);
  104. return(fptr); /* terminate thread */
  105. }
  106. void
  107. write_get_cmd(struct file *fptr)
  108. {
  109. int n;
  110. char line[MAXLINE];
  111. n = snprintf(line, sizeof(line), GET_CMD, fptr->f_name);
  112. Writen(fptr->f_fd, line, n);
  113. printf("wrote %d bytes for %s\n", n, fptr->f_name);
  114. fptr->f_flags = F_READING; /* clears F_CONNECTING */
  115. }
  116. void
  117. home_page(const char *host, const char *fname)
  118. {
  119. int fd, n;
  120. char line[MAXLINE];
  121. fd = Tcp_connect(host, SERV); /* blocking connect() */
  122. n = snprintf(line, sizeof(line), GET_CMD, fname);
  123. Writen(fd, line, n);
  124. for ( ; ; ) {
  125. if ( (n = Read(fd, line, MAXLINE)) == 0)
  126. break; /* server closed connection */
  127. printf("read %d bytes of home page\n", n);
  128. /* do whatever with data */
  129. }
  130. printf("end-of-file on home page\n");
  131. Close(fd);
  132. }