Вход/Регистрация
UNIX: разработка сетевых приложений
вернуться

Стивенс Уильям Ричард

Шрифт:
Возвращение конца файла функцией 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");

69 } else {

70 fprintf(stderr, "%s: wrote %d bytes to stdout\n",

71 gf_time, nwritten);

72 froptr += nwritten; /* только что полученное из функции write

число */

73 if (froptr == friptr)

74 froptr = friptr - fr; /* назад к началу буфера */

75 }

76 }

77 if (FD_ISSET(sockfd, &wset) && ((n - toiptr - tooptr) > 0)) {

78 if ((nwritten = write(sockfd, tooptr, n)) < 0) {

79 if (errno != EWOULDBLOCK)

80 err_sys("write error to socket");

81 } else {

82 fprintf(stderr, "%s: wrote %d bytes to socket\n",

83 gf_time, nwritten);

84 tooptr += nwritten; /* только что полученное из функции write

число */

  • Читать дальше
  • 1
  • ...
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: