-->

UNIX: разработка сетевых приложений

На нашем литературном портале можно бесплатно читать книгу UNIX: разработка сетевых приложений, Стивенс Уильям Ричард-- . Жанр: ОС и Сети. Онлайн библиотека дает возможность прочитать весь текст и даже без регистрации и СМС подтверждения на нашем литературном портале bazaknig.info.
UNIX: разработка сетевых приложений
Название: UNIX: разработка сетевых приложений
Дата добавления: 16 январь 2020
Количество просмотров: 378
Читать онлайн

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

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

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

Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала

1 ... 31 32 33 34 35 36 37 38 39 ... 399 ВПЕРЕД
Перейти на страницу:

 4 {

 5  ssize_t n, rc;

 6  char c, *ptr;

 7  ptr = vptr;

 8  for (n = 1; n < maxlen; n++) {

 9   again:

10   if ((rc = read(fd, &c, 1)) == 1) {

11    *ptr++ = c;

12    if (c == 'n')

13     break; /* записан символ новой строки, как в fgets() */

14   } else if (rc == 0) {

15    if (n == 1)

16     return (0); /* EOF, данные не считаны */

17    else

18     break; /* EOF, некоторые данные были считаны */

19   } else {

20    if (errno == EINTR)

21     goto again;

22    return (-1); /* ошибка, errno задается функцией read() */

23   }

24  }

25  *ptr = 0; /* завершаем нулем, как в fgets() */

26  return (n);

27 }

Если функция чтения или записи (

read
или
write
) возвращает ошибку, то наши функции проверяют, не совпадает ли код ошибки с EINTR (прерывание системного вызова сигналом, см. раздел 5.9). В этом случае прерванная функция вызывается повторно. Мы обрабатываем ошибку в этой функции, чтобы не заставлять процесс снова вызвать
read
или
write
, поскольку целью наших функций является предотвращение обработки нехватки данных вызывающим процессом.

В разделе 14.3 мы покажем, что вызов функции

recv
с флагом
MSG_WAITALL
позволяет обойтись без использования отдельной функции
readn
.

Заметим, что наша функция

readline
вызывает системную функцию
read
один раз для каждого байта данных. Это очень неэффективно, поэтому мы и написали в примечании «Ужасно медленно!». Возникает соблазн обратиться к стандартной библиотеке ввода-вывода (
stdio
). Об этом мы поговорим через некоторое время в разделе 14.8, но учтите, что это может привести к определенным проблемам. Буферизация, предоставляемая
stdio
, решает проблемы с производительностью, но при этом создает множество логистических сложностей, которые в свою очередь порождают скрытые ошибки в приложении. Дело в том, что состояние буферов
stdio
недоступно процессу. Рассмотрим, например, строчный протокол взаимодействия клиента и сервера, причем такой, что могут существовать разные независимые реализации клиентов и серверов (достаточно типичное явление; например, множество веб-браузеров и веб-серверов были разработаны независимо в соответствии со спецификацией HTTP). Хороший стиль программирования заключается в том, что эти программы должны не только ожидать от своих собеседников соблюдения того же протокола, но и контролировать трафик на возможность получения непредвиденного трафика. Подобные нарушения протокола должны рассматриваться как ошибки, чтобы программисты имели возможность находить и устранять неполадки в коде, а также обнаруживать попытки взлома систем. Обработка некорректного трафика должна давать приложению возможность продолжать работу. Буферизация
stdio
мешает достижению перечисленных целей, поскольку приложение не может проверить наличие непредвиденных (некорректных) данных в буферах
stdio
в любой конкретный момент.

Существует множество сетевых протоколов, основанных на использовании строк текста: SMTP, HTTP, FTP, finger. Поэтому соблазн работать со строками будет терзать вас достаточно часто. Наш совет: мыслить в терминах буферов, а не строк. Пишите код таким образом, чтобы считывать содержимое буфера, а не отдельные строки. Если же ожидается получение строки, ее всегда можно поискать в считанном буфере.

В листинге 3.12 приведена более быстрая версия функции

readline
, использующая свой собственный буфер (а не буферизацию
stdio
). Основное достоинство этого буфера состоит в его открытости, благодаря чему вызывающий процесс всегда знает, какие именно данные уже приняты. Несмотря на это, использование
readline
все равно может вызвать проблемы, как мы увидим в разделе 6.3. Системные функции типа
select
ничего не знают о внутреннем буфере
readline
, поэтому неаккуратно написанная программа с легкостью может очутиться в состоянии ожидания в вызове
select
, при том, что данные уже будут находиться в буферах
readline
. По этой причине сочетание вызовов
readn
и
readline
не будет работать так, как этого хотелось бы, пока функция
readn
не будет модифицирована с учетом наличия внутреннего буфера.

Листинг 3.12. Улучшенная версия функции readline

//lib/readline.c

 1 #include "unp.h"

 2 static int read_cnt;

 3 static char *read_ptr;

 4 static char read_buf[MAXLINE];

 5 static ssize_t

 6 my_read(int fd, char *ptr)

 7 {

 8  if (read_cnt <= 0) {

 9   again:

10   if ((read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {

11    if (errno == EINTR)

12     goto again;

13    return(-1);

14   } else if (read_cnt == 0)

15   return(0);

16   read_ptr = read_buf;

17  }

18  read_cnt--;

19  *ptr = *read_ptr++;

20  return(1);

21 }

22 ssize_t

1 ... 31 32 33 34 35 36 37 38 39 ... 399 ВПЕРЕД
Перейти на страницу:
Комментариев (0)
название