Добавить в цитаты Настройки чтения

Страница 187 из 399

В листинге 16.12 показана функция write_get_cmd, посылающая серверу команду HTTP GET.

Листинг 16.12. Отправка команды HTTP GET серверу

//nonblock/write_get_cmd.c

 1 #include "web.h"

 2 void

 3 write_get_cmd(struct file *fptr)

 4 {

 5  int n;

 6  char line[MAXLINE];

 7  n = snprintf(line, sizeof(line), GET_CMD, fptr->f_name);

 8  Writen(fptr->f_fd, line, n);

 9  printf("wrote %d bytes for %sn", n, fptr->f_name);

10  fptr->f_flags = F_READING; /* сброс F_CONNECTING */

11  FD_SET(fptr->f_fd, &rset); /* прочитаем ответ сервера */

12  if (fptr->f_fd > maxfd)

13   maxfd = fptr->f_fd;

14 }

7-9 Команда создается и пишется в сокет.

10-13 Устанавливается флаг F_READING, при этом также сбрасывается флаг F_CONNECTING (если он установлен). Это указывает основному циклу, что данный дескриптор готов для ввода. Также включается дескриптор в наборе чтения, и при необходимости обновляется значение maxfd.

Теперь мы возвращаемся в функцию main, показанную в листинге 16.13, начиная с того места, где закончили в листинге 16.9. Это основной цикл программы: пока имеется ненулевое количество файлов для обработки (значение nlefttoread больше нуля), устанавливается, если это возможно, другое соединение и затем вызывается функция select для всех активных дескрипторов, обрабатывающая как завершение неблокируемых соединений, так и прием данных.

24-35 Если мы не дошли до заданного предела одновременных соединений и есть дополнительные соединения, которые нужно установить, мы ищем еще не обработанный файл (на него указывает нулевое значение f_flags) и вызываем функцию start_co

36-37 Функция select ожидает готовности сокета либо для чтения, либо для записи. Дескрипторы, для которых в настоящий момент происходит установление соединения (неблокируемая функция co

Листинг 16.13. Основной цикл функции main

//nonblock/web.c

24  while (nlefttoread > 0) {

25   while (nco

26    /* find a file to read */

27    for (i =0; i < nfiles; i++)

28     if (file[i].f_flags == 0)

29      break;

30    if (i == nfiles)

31     err_quit("nlefttoco

32    start_co

33    nco

34    nlefttoco

35   }

36   rs = rset:

37   ws = wset;

38   n = Select(maxfd + 1, &rs, &ws, NULL, NULL);

39   for (i = 0; i < nfiles; i++) {

40    flags = file[i].f_flags;

41    if (flags == 0 || flags & F_DONE)

42     continue;

43    fd = file[i].f_fd;

44    if (flags & F_CONNECTING &&

45     (FD_ISSET(fd, &rs) || FD_ISSET(fd, &ws))) {

46     n = sizeof(error);

47     if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &n) < 0 ||

48      error != 0) {

49      err_ret("nonblocking co

50       for %s", file[i].f_name);

51     }

52     /* соединение установлено */

53     printf("co

54     FD_CLR(fd, &wset); /* отключаем запись в этот сокет */

55     write_get_cmd(&file[i]); /* передаем команду GET */

56    } else if (flags & F_READING && FD_ISSET(fd, &rs)) {

57     if ((n = Read(fd, buf, sizeof(buf))) == 0) {

58      printf("end-of-file on %sn", file[i].f_name);

59      Close(fd);

60      file[i].f_flags = F_DONE; /* сбрасывает флаг F_READING */

61      FD_CLR(fd, &rset);

62      nco

63      nlefttoread--;

64     } else {

65      printf("read %d bytes from %sn", n, file[i].f_name);

66     }