UNIX: разработка сетевых приложений, стр. 289
26.6. Веб-клиент и одновременное соединение (продолжение)
Вернемся к нашему примеру с веб-клиентом из раздела 16.5 и перепишем его с использованием потоков вместо неблокируемой функции
connectconnectВ листинге 26.7 показана первая часть нашей программы, глобальные переменные и начало функции
mainЛистинг 26.7. Глобальные переменные и начало функции main
//threads/web01.c 1 #include "unpthread.h" 2 #include <thread.h> /* потоки Solaris */ 3 #define MAXFILES 20 4 #define SERV "80" /* номер порта или имя службы */ 5 struct file { 6 char *f_name; /* имя файла */ 7 char *f_host; /* имя узла или IP-адрес */ 8 int f_fd; /* дескриптор */ 9 int f_flags; /* F_xxx ниже */10 pthread_t f_tid; /* идентификатор потока */11 } file[MAXFILES];12 #define F_CONNECTING 1 /* функция connect () в процессе выполнения */13 #define F_READING 2 /* функция connect() завершена; выполняется считывание */14 #define F_DONE 4 /* все сделано */15 #define GET_CMD "GET %s HTTP/1.0\r\n\r\n"16 int nconn, nfiles, nlefttoconn, nlefttoread;17 void *do_get_read(void*);18 void home_page(const char*, const char*);19 void write_get_cmd(struct file*);20 int21 main(int argc, char **argv)22 {23 int i, n, maxnconn;24 pthread_t tid;25 struct file *fptr;26 if (argc < 5)27 err_quit("usage: web <#conns> <IPaddr> <homepage> file1 ...");28 maxnconn = atoi(argv[1]);29 nfiles = min(argc - 4, MAXFILES);30 for (i = 0; i < nfiles; i++) {31 file[i].f_name = argv[i + 4];32 file[i].f_host = argv[2];33 file[i].f_flags = 0;34 }35 printf("nfiles = %d\n", nfiles);36 home_page(argv[2], argv[3]);37 nlefttoread = nlefttoconn = nfiles;38 nconn = 0;Глобальные переменные
1-16<thread.h><pthread.h>10file_tidselectmaxfd36home_pageЛистинг 26.8. Основной рабочий цикл потока main
//threads/web01.c39 while (nlefttoread > 0) {40 while (nconn < maxnconn && nlefttoconn > 0) {41 /* находим файл для считывания */42 for (i = 0; i < nfiles; i++)43 if (file[i].f_flags == 0)44 break;45 if (i == nfiles)46 err_quit("nlefttoconn = %d but nothing found", nlefttoconn);47 file[i].f_flags = F_CONNECTING;48 Pthread_create(&tid, NULL, &do_get_read, &file[i]);49 file[i].f_tid = tid;50 nconn++;51 nlefttoconn--;52 }53 if ((n = thr_join(0, &tid, (void**)&fptr)) != 0)54 errno = n, err_sys("thr_join error");55 nconn--;56 nlefttoread--;57 printf("thread id %d for %s done\n", tid, fptr->f_name);58 }59 exit(0);60 }По возможности создаем другой поток
40-52nconnmaxconndo_get_readfile