Уильям Стивенс - UNIX: разработка сетевых приложений Страница 124

Тут можно читать бесплатно Уильям Стивенс - UNIX: разработка сетевых приложений. Жанр: Компьютеры и Интернет / Программное обеспечение, год -. Так же Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте 500book.ru или прочесть краткое содержание, предисловие (аннотацию), описание и ознакомиться с отзывами (комментариями) о произведении.
Уильям Стивенс - UNIX: разработка сетевых приложений
  • Категория: Компьютеры и Интернет / Программное обеспечение
  • Автор: Уильям Стивенс
  • Год выпуска: -
  • ISBN: -
  • Издательство: -
  • Страниц: 263
  • Добавлено: 2019-07-03 10:23:38
  • Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних просмотр данного контента СТРОГО ЗАПРЕЩЕН! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту pbn.book@yandex.ru для удаления материала


Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание

Прочтите описание перед тем, как прочитать онлайн книгу «Уильям Стивенс - UNIX: разработка сетевых приложений» бесплатно полную версию:
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.

Уильям Стивенс - UNIX: разработка сетевых приложений читать онлайн бесплатно

Уильям Стивенс - UNIX: разработка сетевых приложений - читать книгу онлайн бесплатно, автор Уильям Стивенс

Традиционно System V возвращала для неблокируемой операции ввода-вывода, которую невозможно выполнить, ошибку EAGAIN, в то время как Беркли-реализации возвращали ошибку EWOULDBLOCK. Еще больше дело запутывается тем, что согласно POSIX.1 используется EAGAIN, в то время как в POSIX.1g определено, что используется EWOULDBLOCK. К счастью, большинство систем (включая SVR4 и 4.4BSD) определяют один и тот же код для этих двух ошибок (проверьте свой системный заголовочный файл <sys/errno.h>), поэтому не важно, какой из них использовать. В нашем тексте мы используем ошибку EWOULDBLOCK, как определяется в POSIX.

В разделе 6.2 мы представили различные модели ввода-вывода и сравнили неблокируемый ввод-вывод с другими моделями. В этой главе мы покажем примеры четырех типов операций и разработаем новый тип клиента, аналогичный веб-клиенту, инициирующий одновременно множество соединений TCP при помощи неблокируемой функции connect.

16.2. Неблокируемые чтение и запись: функция str_cli (продолжение)

Мы снова возвращаемся к нашей функции str_cli, которую мы обсуждали в разделах 5.5 и 6.4. Последняя ее версия, задействующая функцию select, продолжает использовать блокируемый ввод-вывод. Например, если в стандартном устройстве ввода имеется некоторая строка, мы читаем ее с помощью функции fgets и затем отправляем серверу с помощью функции writen. Но вызов функции writen может вызвать блокирование процесса, если буфер отправки сокета полон. В то время как мы заблокированы в вызове функции writen, данные могут быть доступны для чтения из приемного буфера сокета. Аналогично, когда строка ввода доступна из сокета, мы можем заблокироваться в последующем вызове функции fputs, если стандартный поток вывода работает медленнее, чем сеть. Наша цель в данном разделе — создать версию этой функции, использующую неблокируемый ввод-вывод. Блокирование будет предотвращено, благодаря чему в это время мы сможем сделать еще что-то полезное.

К сожалению, добавление неблокируемого ввода-вывода значительно усложняет управление буфером функции, поэтому мы будем представлять функцию частями. Мы также заменим вызовы функций из стандартной библиотеки ввода-вывода на обычные read и write. Это даст возможность отказаться от функций стандартной библиотеки ввода-вывода с неблокируемыми дескрипторами, так как их применение может привести к катастрофическим последствиям.

Мы работаем с двумя буферами: буфер to содержит данные, направляющиеся из стандартного потока ввода к серверу, а буфер fr — данные, приходящие от сервера в стандартный поток вывода. На рис. 16.1 представлена организация буфера to и указателей в буфере.

Рис. 16.1. Буфер, содержащий данные из стандартного потока ввода, идущие к сокету

Указатель toiptr указывает на следующий байт, в который данные могут быть считаны из стандартного потока ввода. Указатель tooptr указывает на следующий байт, который должен быть записан в сокет. Число байтов, которое может быть считано из стандартного потока ввода, равно &to[MAXLINE] минус toiptr. Как только значение tooptr достигает toiptr, оба указателя переустанавливаются на начало буфера.

На рис. 16.2 показана соответствующая организация буфера fr. В листинге 16.1[1] представлена первая часть функции.

Рис. 16.2. Буфер, содержащий данные из сокета, идущие к стандартному устройству вывода

Листинг 16.1. Функция str_cli: первая часть, инициализация и вызов функции

//nonblock/strclinonb.c

 1 #include "unp.h"

 2 void

 3 str_cli(FILE *fp, int sockfd)

 4 {

 5  int maxfdp1, val, stdineof;

 6  ssize_t n, nwritten;

 7  fd_set rset, wset;

 8  char to[MAXLINE], fr[MAXLINE];

 9  char *toiptr, *tooptr, *friptr, *froptr;

10  val = Fcntl(sockfd, F_GETFL, 0);

11  Fcntl(sockfd, F_SETFL, val | O_NONBLOCK);

12  val = Fcntl(STDIN_FILENO, F_SETFL, 0);

13  Fcntl(STDIN_FILENO, F_SETFL, val | O_NONBLOCK);

14  val = Fcntl(STDOUT_FILENO, F_SETFL, 0);

15  Fcntl(STDOUT_FILENO, F_SETFL, val | O_NONBLOCK);

16  toiptr = tooptr = to; /* инициализация указателей буфера */

17  friptr = froptr = fr;

18  stdineof = 0;

19  maxfdp1 = max(max(STDIN_FILENO, STDOUT_FILENO), sockfd) + 1;

20  for (;;) {

21   FD_ZERO(&rset);

22   FD_ZERO(&wset);

23   if (stdineof == 0 && toiptr < &to[MAXLINE])

24     FD_SET(STDIN_FILENO, &rset); /* чтение из стандартного потока

                                       ввода */

25   if (friptr < &fr[MAXLINE])

26    FD_SET(sockfd, &rset); /* чтение из сокета */

27   if (tooptr != toiptr)

28    FD_SET(sockfd, &wset); /* данные для записи в сокет */

29   if (froptr != friptr)

30    FD_SET(STDOUT_FILENO, &wset); /* данные для записи в стандартный

                                       поток вывода */

31   Select(maxfdp1, &rset, &wset, NULL, NULL);

Установка неблокируемых дескрипторов

10-15 Все три дескриптора делаются неблокируемыми при помощи функции fcntl: сокет в направлении к серверу и от сервера, стандартный поток ввода и стандартный поток вывода.

Инициализация указателей буфера

16-19 Инициализируются указатели в двух буферах и вычисляется максимальный дескриптор. Это значение, увеличенное на единицу, будет использоваться в качестве первого аргумента функции select.

Основной цикл: подготовка к вызову функции select

20 Как и в случае первой версии этой функции, показанной в листинге 6.2, основной цикл функции содержит вызов функции select, за которой следуют отдельные проверки различных интересующих нас условий.

Подготовка интересующих нас дескрипторов

21-30 Оба набора дескрипторов обнуляются и затем в каждом наборе включается не более двух битов. Если мы еще не прочитали конец файла из стандартного потока ввода и есть место как минимум для 1 байта данных в буфере to, то в наборе флагов чтения включается бит, соответствующий стандартному потоку ввода. Если есть место как минимум для 1 байта данных в буфере fr, то в наборе флагов чтения включается бит, соответствующий сокету. Если есть данные для записи в сокет в буфере to, то в наборе флагов записи включается бит, соответствующий сокету. Наконец если в буфере fr есть данные для отправки в стандартный поток вывода, то в наборе флагов записи включается бит, соответствующий этому стандартному потоку.

Вызов функции select

31 Вызывается функция select, ожидающая, когда одно из четырех условий станет истинным. Для этой функции мы не задаем тайм-аута.

Следующая часть нашей функции показана в листинге 16.2. Этот код содержит первые две проверки (из четырех возможных), выполняемые после завершения функции select.

Листинг 16.2. Функция str_cli: вторая часть, чтение из стандартного потока ввода или сокета

//nonblock/strclinonb.c

32   if (FD_ISSET(STDIN_FILENO, &rset)) {

33    if ((n = read(STDIN_FILENO, toiptr, &to[MAXLINE] - toiptr)) < 0) {

34     if (errno != EWOULDBLOCK)

35      err_sys("read error on stdin");

36    } else if (n == 0) {

37     fprintf(stderr, "%s: EOF on stdin\n", gf_time());

38     stdineof = 1; /* с stdin все сделано */

39     if (tooptr == toiptr)

40      Shutdown(sockfd, SHUT_WR); /* отсылаем FIN */

41    } else {

42     fprintf(stderr, "%s: read %d bytes from stdin\n", gf_time(),

43      n);

44     toiptr += n; /* только что полученное из функции read число */

45     FD_SET(sockfd, &wset); /* включаем бит в наборе чтения */

46    }

47   }

48   if (FD_ISSET(sockfd, &rset)) {

49    if ((n = read(sockfd, friptr, &fr[MAXLINE] - friptr)) < 0) {

50     if (errno != EWOULDBLOCK)

51      err_sys("read error on socket");

52    } else if (n == 0) {

53     fprintf(stderr, "%s: EOF on socket\n", gf_time());

54     if (stdineof)

55      return; /* нормальное завершение */

56     else

57      err_quit("str_cli: server terminated prematurely");

58    } else {

59     fprintf(stderr, "%s: read %d bytes from socket\n",

60      gf_time(), n);

61     friptr += n; /* только что полученное из функции read число */

62     FD_SЕТ(STDOUT_FILЕNO, &wset); /* включаем бит в наборе

                                        чтения */

63    }

64   }

Чтение из стандартного потока ввода с помощью функции read

32-33 Если стандартный поток ввода готов для чтения, мы вызываем функцию read. Третий ее аргумент — это количество свободного места в буфере to.

Перейти на страницу:
Вы автор?
Жалоба
Все книги на сайте размещаются его пользователями. Приносим свои глубочайшие извинения, если Ваша книга была опубликована без Вашего на то согласия.
Напишите нам, и мы в срочном порядке примем меры.
Комментарии / Отзывы
    Ничего не найдено.