-->

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

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

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

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

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

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

Перейти на страницу:

37     fprintf(stderr, "%s: EOF on stdinn", 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 stdinn", 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 socketn", 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 socketn",

60      gf_time(), n);

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

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

                                        чтения */

63    }

64   }

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

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

Обработка ошибки

34-35
 Если происходит ошибка
EWOULDBLOCK
, мы ничего не предпринимаем. Обычно эта ситуация — когда функция
select
сообщает нам о том, что дескриптор готов для чтения, а функция read возвращает ошибку
EWOULDBLOCK
— не должна возникать, но тем не менее мы ее обрабатываем.

Возвращение конца файла функцией read

36-40
 Если функция
read
возвращает нуль, мы закончили со стандартным потоком ввода. Флаг
stdineof
установлен. Если в буфере to больше нет данных для отправки (
tooptr
равно
toiptr
), функция
shutdown
отправляет серверу сегмент FIN. Если в буфере
to
еще есть данные для отправки, сегмент FIN не может быть отправлен до тех пор, пока содержимое буфера не будет записано в сокет.

ПРИМЕЧАНИЕ

Мы выводим в стандартный поток сообщений об ошибках строку, отмечающую конец файла, вместе с текущим временем. Мы покажем, как мы используем этот вывод, после описания функции. Аналогичные вызовы функции fprintf выполняются неоднократно в процессе выполнения нашей функции.

Возвращение данных функцией read

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

ПРИМЕЧАНИЕ

Это одно из непростых конструктивных решений, которые приходится принимать при написании кода. У нас есть несколько альтернатив. Вместо установки бита в наборе записи мы можем ничего не делать, и в этом случае функция select будет проверять возможность записи в сокет, когда она будет вызвана в следующий раз. Но это требует дополнительного прохода цикла и вызова функции select, когда мы уже знаем, что у нас есть данные для записи в сокет. Другой вариант — дублировать код, который записывает в сокет, но это кажется расточительным, к тому же это возможный источник ошибки (в случае, если в этой части дублируемого кода есть ошибка и мы обнаруживаем и устраняем ее только в одном месте). Наконец, мы можем создать функцию, записывающую в сокет, и вызывать эту функцию вместо дублирования кода, но эта функция должна использовать три локальные переменные совместно с функцией str_cli, что может привести к необходимости сделать эти переменные глобальными. Выбор, сделанный в нашем случае, — это результат субъективного мнения автора относительно того, какой из описанных трех вариантов предпочтительнее.

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

48-64
Эти строки кода аналогичны выражению
if
, только что описанному для случая, когда стандартный поток ввода готов для чтения. Если функция
read
возвращает ошибку
EWOULDBLOCK
, ничего не происходит. Если мы встречаем признак конца файла, присланный сервером, это нормально, когда мы уже получили признак конца файла в стандартном потоке ввода. Но иначе это будет ошибкой, означающей преждевременное завершение работы сервера (
Server terminated prematurely
). Если функция
read
возвращает некоторые данные,
friptr
увеличивается на единицу и в наборе флагов записи включается бит для стандартного потока вывода, с тем чтобы попытаться записать туда данные в следующей части функции.

В листинге 16.3 показана последняя часть нашей функции.

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

//nonblock/strclinonb.c

65   if (FD_ISSET(STDOUT_FILENO, &wset) && ((n = friptr - froptr) > 0)) {

66    if ((nwritten = write(STDOUT_FILENO, froptr, n)) < 0) {

67     if (errno != EWOULDBLOCK)

68      err_sys("write error to stdout");

Перейти на страницу:
Комментариев (0)
название