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

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

Шрифт:
Основной цикл: подготовка к вызову функции 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
.

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

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

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

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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