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

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

Читать бесплатно Уильям Стивенс - UNIX: разработка сетевых приложений. Жанр: Программное обеспечение издательство -, год 2004. Так же читаем полные версии (весь текст) онлайн без регистрации и SMS на сайте kniga-online.club или прочесть краткое содержание, предисловие (аннотацию), описание и ознакомиться с отзывами (комментариями) о произведении.
Перейти на страницу:

Существует два основных типа параметров: двоичные параметры, включающие или отключающие определенное свойство (флаги), и параметры, получающие и возвращающие значения параметров, которые мы можем либо задавать, либо проверять. В колонке «Флаг» указывается, относится ли параметр к флагам. Для флагов при вызове функции getsockopt аргумент *optval является целым числом. Возвращаемое значение *optval нулевое, если параметр отключен, и ненулевое, если параметр включен. Аналогично, функция setsockopt требует ненулевого значения *optval для включения параметра, и нулевого значения — для его выключения. Если в колонке «Флаг» не содержится символа «•», то параметр используется для передачи значения заданного типа между пользовательским процессом и системой.

В последующих разделах этой главы приводятся дополнительные подробности о параметрах сокетов.

7.3. Проверка наличия параметра и получение значения по умолчанию

Напишем программу, которая проверяет, поддерживается ли большинство параметров, представленных в табл. 7.1 и 7.2, и если да, то выводит их значения, заданные по умолчанию. В листинге 7.1[1] содержатся объявления нашей программы.

Листинг 7.1. Объявления для нашей программы, проверяющей параметры сокетов

//sockopt/checkopts.с

 1 #include "unp.h"

 2 #include <netinet/tcp.h> /* определения констант TCP_xxx */

 3 union val {

 4  int i_val;

 5  long l_val;

 6  struct linger linger_val;

 7  struct timeval timeval_val;

 8 } val;

 9 static char *sock_str_flag(union val*, int);

10 static char *sock_str_int(union val*, int);

11 static char *sock_str_linger(union val*, int);

12 static char *sock_str_timeval(union val*, int);

13 struct sock_opts {

14  const char *opt_str;

15  int opt_level;

16  int opt_name;

17  char *(*opt_val_str)(union val*, int);

18 } sock_opts[] = {

19  { "SO_BROADCAST",      SOL_SOCKET,   SO_BROADCAST,   sock_str_flag },

20  { "SO_DEBUG",          SOL_SOCKET,   SO_DEBUG,       sock_str_flag },

21  { "SO_DONTROUTE",      SOL_SOCKET,   SO_DONTROUTE,   sock_str_flag },

22  { "SO_ERROR",          SOL_SOCKET,   SO_ERROR,       sock_str_int },

23  { "SO_KEEPALIVE",      SOL_SOCKET,   SO_KEEPALIVE,   sock_str_flag },

24  { "SO_LINGER",         SOL_SOCKET,   SO_LINGER,      sock_str_linger },

25  { "SO_OOBINLINE",      SOL_SOCKET,   SO_OOBINLINE,   sock_str_flag },

26  { "SO_RCVBUF",         SOL_SOCKET,   SO_RCVBUF,      sock_str_int },

27  { "SO_SNDBUF",         SOL_SOCKET,   SO_SNDBUF,      sock_str_int },

28  { "SO_RCVLOWAT",       SOL_SOCKET,   SO_RCVLOWAT,    sock_str_int },

29  { "SO_SNDLOWAT",       SOL_SOCKET,   SO_SNDLOWAT,    sock_str_int },

30  { "SO_RCVTIMEO",       SOL_SOCKET,   SO_RCVTIMEO,    sock_str_timeval },

31  { "SO_SNDTIMEO",       SOL_SOCKET,   SO_SNDTIMEO,    sock_str_timeval },

32  { "SO_REUSEADDR",      SOL_SOCKET,   SO_REUSEADDR,   sock_str_flag },

33 #ifdef SO_REUSEPORT

34  { "SO_REUSEPORT",      SOL_SOCKET,   SO_REUSEPORT,   sock_str_flag },

35 #else

36  { "SO_REUSEPORT",      0,            0, NULL },

37 #endif

38  { "SO_TYPE",           SOL_SOCKET,   SO_TYPE,        sock_str_int },

39  { "SO_USELOOPBACK",    SOL_SOCKET,   SO_USELOOPBACK, sock_str_flag },

40  { "IP_TOS",            IPPROTO_IP,   IP_TOS,         sock_str_int },

41  { "IP_TTL",            IPPROTO_IP,   IP_TTL,         sock_str_int },

42  { "IPV6_DONTFRAG",     IPPROTO_IPV6, IPV6_DONTFRAG,  sock_str_flag },

43  { "IPV6_UNICAST_HOPS", IPPROTO_IPV6, IPV6_UNICAST_HOPS, sock_str_int },

44  { "IPV6_V6ONLY",       IPPROTO_IPV6, IPV6_V6ONLY,    sock_str_flag },

45  { "TCP_MAXSEG",        IPPROTO_TCP,  TCP_MAXSEG,     sock_str_int },

46  { "TCP_NODELAY",       IPPROTO_TCP,  TCP_NODELAY,    sock_str_flag },

47  { "SCTP_AUTOCLOSE",    IPPROTO_SCTP, SCTP_AUTOCLOSE, sock_str_int },

48  { "SCTP_MAXBURST",     IPPROTO_SCTP, SCTP_MAXBURST,  sock_str_int },

49  { "SCTP_MAXSEG",       IPPROTO_SCTP, SCTP_MAXSEG,    sock_str_int },

50  { "SCTP_NODELAY",      IPPROTO_SCTP, SCTP_NODELAY,   sock_str_flag },

51  { NULL,                0,            0,              NULL }

52 };

Объявление объединения возможных значений

3-9 Наше объединение val содержит по одному элементу для каждого возможного возвращаемого значения из функции getsockopt.

Задание прототипов функций

10-13 Мы определяем прототипы для четырех функций, которые вызываются для вывода значения данного параметра сокета.

Задание структуры и инициализация массива

14-46 Наша структура sock_opts содержит всю информацию, которая необходима, чтобы вызвать функцию getsockopt для каждого из параметров сокета и вывести его текущее значение. Последний элемент, opt_val_str, является указателем на одну из четырех функций, которые выводят значение параметра. Мы размещаем в памяти и инициализируем массив этих структур, каждый элемент которого соответствует одному параметру сокета.

ПРИМЕЧАНИЕ

Не все реализации поддерживают полный набор параметров сокетов. Чтобы определить, поддерживается ли данный параметр, следует использовать #ifdef или #if defined, как показано для параметра SO_REUSEPORT. Для полноты картины требуется обработать подобным образом все параметры, но в книге мы пренебрегаем этим, потому что #ifdef только удлиняет показанный код и не влияет на суть дела.

В листинге 7.2 показана наша функция main.

Листинг 7.2. Функция main для проверки параметров сокетов

//sockopt/checkopts.c

53 int

54 main(int argc, char **argv)

55 {

56  int fd;

57  socklen_t len;

58  struct sock_opts *ptr;

59  for (ptr = sock_opts; ptr->opt_str != NULL; ptr++) {

60   printf("%s: ptr->opt_str);

61   if (ptr->opt_val_str == NULL)

62    printf("(undefined)n");

63   else {

64    switch(ptr->opt_level) {

65    case SOL_SOCKET:

66    case IPPROTO_IP:

67    case IPPROTO_TCP:

68     fd = Socket(AF_INET, SOCK_STREAM, 0);

69     break;

70 #ifdef IPV6

71    case IPPROTO_IPV6:

72     fd = Socket(AF_INET6, SOCK_STREAM, 0);

73     break;

74 #endif

75 #ifdef IPPROTO_SCTP

76    case IPPROTO_SCTP:

77     fd = Socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);

78     break;

79 #endif

80    default:

81     err_quit("Can't create fd for level %dn", ptr->opt_level);

82    }

83    len = sizeof(val);

84    if (getsockopt(fd, ptr->opt_level, ptr->opt_name,

85     &val, &len) == -1) {

86     err_ret("getsockopt error");

87    } else {

88     printf("default = %sn", (*ptr->opt_val_str)(&val, len));

89    }

90    close(fd);

91   }

92  }

93  exit(0);

94 }

Перебор всех параметров

59-63 Мы перебираем все элементы нашего массива. Если указатель opt_val_str пустой, то параметр не определен реализацией (что, как мы показали, возможно для SO_REUSEPORT).

Создание сокета

63-82 Мы создаем сокет, на котором проверяем действие параметров. Для проверки параметров сокета и уровней IPv4 и TCP мы используем сокет IPv4 TCP. Для проверки параметров сокетов уровня IPv6 мы используем сокет IPv6 TCP, а для проверки параметров SCTP — сокет IPv4 SCTP.

Вызов функции getsockopt

83-87 Мы вызываем функцию getsockopt, но не завершаем ее выполнение, если возвращается ошибка. Многие реализации определяют имена некоторых параметров сокетов, даже если не поддерживают эти параметры. Неподдерживаемые параметры выдают ошибку ENOPROTOOPT.

Вывод значения параметра по умолчанию

88-89 Если функция getsockopt успешно завершается, мы вызываем нашу функцию для преобразования значения параметра в строку и выводим эту строку.

В листинге 7.1 мы показали четыре прототипа функций, по одному для каждого типа возвращаемого значения параметра. В листинге 7.3 показана одна из этих функций, sock_str_flag, которая выводит значение параметра, являющегося флагом. Другие три функции аналогичны этой.

Листинг 7.3. Функция sock_str_flag: преобразование флага в строку

//sockopt/checkopts.с

 95 static char strres[128];

 96 static char *

 97 sock_str_flag(union val *ptr, int len)

 98 {

 99  if (len != sizeof(int))

100   snprint(strres, sizeof(strres), "size (%d) not sizeof(int)", len);

101  else

102   snprintf(strres, sizeof(strres),

103    "%s", (ptr->i_val == 0) ? "off" : "on");

104  return(strres);

105 }

99-104 Вспомните, что последний аргумент функции getsockopt — это аргумент типа «значение-результат». Первое, что мы проверяем, — это то, что размер значения, возвращаемого функцией getsockopt, совпадает с предполагаемым. В зависимости от того, является ли значение флага нулевым или нет, возвращается строка off или on.

Выполнение этой программы под FreeBSD 4.8 с пакетами обновлений KAME SCTP дает следующий вывод:

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

Уильям Стивенс читать все книги автора по порядку

Уильям Стивенс - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки kniga-online.club.


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

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


Уважаемые читатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.

  • 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
  • 2. Просьба отказаться от оскорблений, угроз и запугиваний.
  • 3. Просьба отказаться от нецензурной лексики.
  • 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.

Надеемся на Ваше понимание и благоразумие. С уважением, администратор kniga-online.


Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*