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