Категории
Самые читаемые
PochitayKnigi » Компьютеры и Интернет » Программное обеспечение » UNIX: разработка сетевых приложений - Уильям Стивенс

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

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

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 248 249 250 251 252 253 254 255 256 ... 263
Перейти на страницу:

Наши функции обработки ошибок используют следующую возможность ANSI С: список аргументов может иметь переменную длину. Более подробную информацию об этом вы найдете в разделе 7.3 книги [68].

В табл. Г.1 показано, в чем заключаются различия между функциями обработки ошибок. Если глобальная целочисленная переменная daemon_proc отлична от нуля, то сообщение об ошибке передается функции syslog с указанным уровнем, в противном случае оно отправляется в стандартный поток вывода сообщений об ошибках.

Таблица Г.1. Стандартные функции обработки ошибок

Функция strerror (errno ?) Завершение ? Уровень syslog err_dump Да abort(); LOG_ERR err_msg Нет return; LOG_INFO err_quit Нет exit(1); LOG_ERR err_ret Да return; LOG_INFO err_sys Да exit(1); LOG_ERR

В листинге Г.3 показаны первые пять функций из табл. Г.1.

Листинг Г.3. Стандартные функции обработки ошибок

//lib/error.c

 1 #include "unp.h"

 2 #include <stdarg.h> /* заголовочный файл ANSI С */

 3 #include <syslog.h> /* для syslog() */

 4 int daemon_proc; /* устанавливается в ненулевое значение с

                       помощью daemon_init() */

 5 static void err_doit(int, int, const char*, va_list);

 6 /* Нефатальная ошибка, связанная с системным вызовом.

 7    Выводим сообщение и возвращаем управление */

 8 void

 9 err_ret(const char *fmt , ...)

10 {

11  va_list ap;

12  va_start(ap, fmt);

13  err_doit(1, LOG_INFO, fmt, ap);

14  va_end(ap);

15  return;

16 }

17 /* Фатальная ошибка, связанная с системным вызовом.

18    Выводим сообщение и завершаем работу */

19 void

20 err_sys(const char *fmt)

21 {

22  va_list ap;

23  va_start(ap, fmt);

24  err_doit(1, LOG_ERR, fmt, ap);

25  va_end(ap);

26  exit(1);

27 }

28 /* Фатальная ошибка, связанная с системным вызовом.

29    Выводим сообщение, сохраняем дамп памяти процесса и заканчиваем работу */

30 void

31 err_dump(const char *fmt, ... )

32 {

33  va_list ар;

34  va_start(ap, fmt);

35  err_doit(1, LOG_ERR, fmt, ap);

36  va_end(ap);

37  abort(); /* сохраняем дамп памяти и заканчиваем работу */

38  exit(1);

39 }

40 /* Нефатальная ошибка, не относящаяся к системному вызову.

41    Выводим сообщение и возвращаем управление */

42 void

43 err_msg(const char *fmt , ...)

44 {

45  va_list ap;

46  va_start(ap, fmt);

47  err_doit(0, LOG_INFO, fmt, ap);

48  va_end(ap);

49  return;

50 }

51 /* Фатальная ошибка, не относящаяся к системному вызову.

52    Выводим сообщение и заканчиваем работу. */

53 void

54 err_quit(const char *fmt, ...)

55 {

56  va_list ap;

57  va_start(ap, fmt);

58  err_doit(0, LOG_ERR, fmt, ap);

59  va_end(ap);

60  exit(1);

61 }

62 /* Выводим сообщение и возвращаем управление.

63    Вызывающий процесс задает "errnoflag" и "level" */

64 static void

65 err_doit(int errnoflag, int level, const char *fmt, va_list ap)

66 {

67  int errno_save, n;

68  char buf[MAXLINE + 1];

69  errno_save = errno; /* значение может понадобиться вызвавшему

                           процессу */

70 #ifdef HAVE_VSNPRINTF

71  vsnprintf(buf, MAXLINE, fmt, ap); /* защищенный вариант */

72 #else

73  vsprintf(buf, fmt, ap); /* незащищенный вариант */

74 #endif

75  n = strlen(buf);

76  if (errnoflag)

77   snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save));

78  strcat(buf, "n");

79  if (daemon_proc) {

80   syslog(level, buf);

81  } else {

82   fflush(stdout); /* если stdout и stderr совпадают */

83   fputs(buf, stderr);

84   fflush(stderr);

85  }

86  return;

87 }

Приложение Д

Решения некоторых упражнений

Глава 1

1.3. В операционной системе Solaris получаем:

solaris % daytimetcpcli 127.0.0.1

socket error: Protocol not supported

Для получения дополнительной информации об этой ошибке сначала используем программу grep, чтобы найти строку Protocol not supported в заголовочном файле <sys/errno.h>.

solaris % grep 'Protocol not supported' /usr/include/sys/errno.h

#define EPROTONOSUPPORT 120 /* Protocol not supported */

Это значение errno возвращается функцией socket. Далее смотрим в руководство пользователя:

solaris % man socket

В большинстве руководств пользователя в конце под заголовком «Errors» приводится дополнительная, хотя и лаконичная информация об ошибках.

1.4. Заменяем первое описание на следующее:

int sockfd, n, counter = 0;

Добавляем оператор

counter++;

в качестве первого оператора цикла while. Наконец, прежде чем прервать программу, выполняем

printf("counter = %dn", counter);

На экран всегда выводится значение 1.

1.5. Объявим переменную i типа int и заменим вызов функции write на следующий:

for (i = 0; i < strlen(buff); i++)

 Write(connfd, &buff[i], 1);

Результат зависит от расположения клиентского узла и узла сервера. Если клиент и сервер находятся на одном узле, счетчик обычно равен 1. Это значит, что даже если сервер выполнит функцию write 26 раз, данные будут возвращены за одну операцию считывания (read). Но если клиент запущен в Solaris 2.5.1, а сервер в BSD/OS 3.0, счетчик обычно равен 2. Просмотрев пакеты Ethernet, мы увидим, что первый символ отправляется в первом пакете сам по себе, а следующий пакет содержит остальные 25 символов. (Обсуждение алгоритма Нагла в разделе 7.9 объясняет причину такого поведения.)

Цель этого примера — продемонстрировать, что разные реализации TCP по-разному поступают с данными, поэтому наше приложение должно быть готово считывать данные как поток байтов, пока не будет достигнут конец потока.

Глава 2

2.1 Зайдите на веб-страницу http://www.iana.org/numbers.htm и найдите журнал под названием «IP Version Number». Номер версии 0 зарезервирован, версии 1-3 не использовались, а версия 5 представляет собой потоковый протокол Интернета (Internet Stream Protocol).

2.2. Все RFC бесплатно доступны по электронной почте, через FTP или Web. Стартовая страница для поиска находится по адресу http://www.ietf.org. Одним из мест расположения RFC является каталог ftp://ftp.isi.edu/in-notes. Для начала следует получить файл с текущим каталогом RFC, обычно это файл rfc-index.txt. HTML-версия хранится в файле http://www.rfc-editor.org/rfc-index.html. Если с помощью какого-либо редактора осуществить поиск термина «stream» (поток) в указателе RFC, мы выясним, что RFC 1819 определяет версию 2 потокового протокола Интернета. Какую бы информацию, которая может содержаться в RFC, мы ни искали, для поиска следует использовать указатель (каталог) RFC.

2.3. В версии IPv4 при таком значении MSS генерируется 576-байтовая дейтаграмма (20 байт для заголовка IPv4 и 20 байт для заголовка TCP). Это минимальный размер буфера для сборки фрагментов в Ipv4.

2.4. В данном примере сервер (а не клиент) осуществляет активное закрытие.

2.5. Узел в сети Token Ring не может посылать пакет, содержащий больше, чем 1460 байт данных, поскольку полученное им значение MSS равно 1460. Узел в сети Ethernet может посылать пакет размером до 4096 байт данных, но не превышающий величину MTU исходящего интерфейса (Ethernet) во избежание фрагментации. Протокол TCP не может превысить величину MSS, объявленную другой стороной, но он всегда может посылать пакеты меньшего размера.

2.6. В разделе «Protocol Numbers» (номера протоколов) RFC «Assigned Numbers» («Присвоенные номера») указано значение 89 для протокола OSPF.

2.7. Выборочное уведомление указывает лишь на получение пакетов с конкретными последовательными номерами. Кумулятивное уведомление сообщает о получении данных вплоть до конкретного порядкового номера (включительно). При освобождении буфера отправки в соответствии с выборочным уведомлением система может удалять только те данные, доставка которых была подтверждена явно, но не те, номера которых меньше или больше подтвержденных.

1 ... 248 249 250 251 252 253 254 255 256 ... 263
Перейти на страницу:
Тут вы можете бесплатно читать книгу UNIX: разработка сетевых приложений - Уильям Стивенс.
Комментарии