| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- /* Doesn't work right. Main thread sucks up all the CPU time polling unless
- we call thr_yield(). */
- #include "unpthread.h"
- #include <thread.h> /* Solaris threads */
- #define MAXFILES 20
- #define SERV "80" /* port number or service name */
- struct file {
- char *f_name; /* filename */
- char *f_host; /* hostname or IP address */
- int f_fd; /* descriptor */
- int f_flags; /* F_xxx below */
- pthread_t f_tid; /* thread ID */
- } file[MAXFILES];
- #define F_CONNECTING 1 /* connect() in progress */
- #define F_READING 2 /* connect() complete; now reading */
- #define F_DONE 4 /* all done */
- #define F_JOINED 8 /* main has pthread_join'ed */
- int nconn, nfiles, nlefttoconn, nlefttoread;
- char get[] = "GET / HTTP/1.0\r\n\r\n"; /* for home page */
- int ndone; /* number of terminated threads & mutex */
- pthread_mutex_t ndone_mutex = PTHREAD_MUTEX_INITIALIZER;
- void *do_get_read(void *);
- void home_page(const char *, const char *);
- void write_get_cmd(struct file *);
- int
- main(int argc, char **argv)
- {
- int i, n, maxnconn;
- pthread_t tid;
- struct file *fptr;
- if (argc < 5)
- err_quit("usage: web <#conns> <IPaddr> <homepage> file1 ...");
- maxnconn = atoi(argv[1]);
- nfiles = min(argc - 4, MAXFILES);
- for (i = 0; i < nfiles; i++) {
- file[i].f_name = argv[i + 4];
- file[i].f_host = argv[2];
- file[i].f_flags = 0;
- }
- printf("nfiles = %d\n", nfiles);
- home_page(argv[2], argv[3]);
- nlefttoread = nlefttoconn = nfiles;
- nconn = 0;
- while (nlefttoread > 0) {
- /* printf("nconn = %d, nlefttoconn = %d\n", nconn, nlefttoconn); */
- while (nconn < maxnconn && nlefttoconn > 0) {
- /* find a file to read */
- for (i = 0 ; i < nfiles; i++)
- if (file[i].f_flags == 0)
- break;
- if (i == nfiles)
- err_quit("nlefttoconn = %d but nothing found", nlefttoconn);
- if ( (n = pthread_create(&tid, NULL, &do_get_read, &file[i])) != 0)
- errno = n, err_sys("pthread_create error");
- printf("created thread %d\n", tid);
- file[i].f_tid = tid;
- file[i].f_flags = F_CONNECTING;
- nconn++;
- nlefttoconn--;
- }
- thr_yield();
- /* See if one of the threads is done */
- if ( (n = pthread_mutex_lock(&ndone_mutex)) != 0)
- errno = n, err_sys("pthread_mutex_lock error");
- if (ndone > 0) {
- for (i = 0; i < nfiles; i++) {
- if (file[i].f_flags & F_DONE) {
- if ( (n = pthread_join(file[i].f_tid, (void **) &fptr)) != 0)
- errno = n, err_sys("pthread_join error");
-
- if (&file[i] != fptr)
- err_quit("file[i] != fptr");
- fptr->f_flags = F_JOINED; /* clears F_DONE */
- ndone--;
- nconn--;
- nlefttoread--;
- printf("thread id %d for %s done\n",
- file[i].f_tid, fptr->f_name);
- }
- }
- }
- if ( (n = pthread_mutex_unlock(&ndone_mutex)) != 0)
- errno = n, err_sys("pthread_mutex_unlock error");
- }
- exit(0);
- }
- void *
- do_get_read(void *vptr)
- {
- int fd, n;
- char line[MAXLINE];
- struct file *fptr;
- fptr = (struct file *) vptr;
- fd = Tcp_connect(fptr->f_host, SERV);
- fptr->f_fd = fd;
- printf("do_get_read for %s, fd %d, thread %d\n",
- fptr->f_name, fd, fptr->f_tid);
- write_get_cmd(fptr); /* write() the GET command */
- /* Read server's reply */
- for ( ; ; ) {
- if ( (n = read(fd, line, MAXLINE)) <= 0) {
- if (n == 0)
- break; /* server closed connection */
- else
- err_sys("read error");
- }
- printf("read %d bytes from %s\n", n, fptr->f_name);
- }
- printf("end-of-file on %s\n", fptr->f_name);
- close(fd);
- fptr->f_flags = F_DONE; /* clears F_READING */
- if ( (n = pthread_mutex_lock(&ndone_mutex)) != 0)
- errno = n, err_sys("pthread_mutex_lock error");
- ndone++;
- if ( (n = pthread_mutex_unlock(&ndone_mutex)) != 0)
- errno = n, err_sys("pthread_mutex_unlock error");
- return(fptr); /* terminate thread */
- }
- void
- write_get_cmd(struct file *fptr)
- {
- int n;
- char line[MAXLINE];
- strcpy(line, "GET ");
- strcat(line, fptr->f_name);
- strcat(line, " HTTP/1.0\r\n\r\n");
- n = strlen(line);
- if (writen(fptr->f_fd, line, n) != n)
- err_sys("writen error");
- printf("wrote %d bytes for %s\n", n, fptr->f_name);
- fptr->f_flags = F_READING; /* clears F_CONNECTING */
- }
- void
- home_page(const char *host, const char *fname)
- {
- int fd, n;
- char line[MAXLINE];
- fd = Tcp_connect(host, SERV);
- strcpy(line, "GET ");
- strcat(line, fname);
- strcat(line, " HTTP/1.0\r\n\r\n");
- n = strlen(line);
- if (writen(fd, line, n) != n)
- err_sys("writen error");
- for ( ; ; ) {
- if ( (n = read(fd, line, MAXLINE)) <= 0) {
- if (n == 0)
- break; /* server closed connection */
- else
- err_sys("read error");
- }
- printf("read %d bytes of home page\n", n);
- /* do whatever with data */
- }
- printf("end-of-file on home page\n");
- close(fd);
- }
|