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

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

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

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 175 176 177 178 179 180 181 182 183 ... 263
Перейти на страницу:

Последняя из новых функций называется sctp_print_addresses. Она выводит на экран адреса из списка, возвращаемого функциями sctp_getpaddrs и sctp_getladdrs. Текст функции представлен в листинге 23.12.

Листинг 23.12. Вывод списка адресов

//sctp/sctp_print_addrs.c

 1 #include "unp.h"

 2 void

 3 sctp_print_addresses(struct sockaddr_storage *addrs, int num)

 4 {

 5  struct sockaddr_storage *ss;

 6  int i, salen;

 7  ss = addrs;

 8  for (i=0; i<num; i++){

 9   printf("%sn", Sock_ntop((SA*)ss, salen));

10 #ifdef HAVE_SOCKADDR_SA_LEN

11   salen = ss->ss_len;

12 #else

13   swilch (ss->ss_family) {

14   case AF_INET:

15    salen = sizeof(struct sockaddr_in);

16    break;

17 #ifdef IPV6

18   case AF_INET6:

19    salen = sizeof(struct sockaddr_in6);

20    break;

21 #endif

22   default:

23    err_auit("sctp_print_addresses: unknown AF");

24    break;

25   }

26 #endif

27   ss = (struct sockaddr_storage*)((char*)ss + salen);

28  }

29 }

Последовательная обработка адресов

7-8 Функция перебирает адреса в цикле. Общее количество адресов указывается вызывающим процессом.

Вывод адреса

9 Адрес преобразуется к удобочитаемому виду функцией sock_ntop, которая, как вы помните, должна работать со структурами адреса сокета всех форматов, поддерживаемых системой.

Определение размера адреса

10-26 Список адресов передается в упакованном формате. Это не просто массив структур sockaddr_storage. Дело в том, что структура sockaddr_storage достаточно велика, и ее нецелесообразно использовать при передаче адресов между ядром и пользовательскими процессами. В системах, где эта структура содержит внутреннее поле длины, обработка списка является делом тривиальным: достаточно извлекать длину из текущей структуры sockaddr_storage. В прочих системах длина определяется на основании семейства адреса. Если семейство не определено, функция завершает работу с сообщением об ошибке.

Перемещение указателя

27 К указателю на элемент списка прибавляется размер адреса. Таким образом осуществляется перемещение по списку адресов.

Выполнение программы

Результат взаимодействия модифицированного клиента с сервером представлен ниже.

FreeBSD-lap: ./sctpclient01 10.1.1.5

[0]Hi

There are 2 remote addresses and they are:

10.1.1.5:9877

127.0.0.1:9877

There are 2 local addresses and they are:

10.1.1.5:1025

127.0.0.1:1025

From str:0 seq:0 (assoc:c99e2680):[0]Hi

Control-D

FreeBSD-lap:

23.8. Определение идентификатора ассоциации по IP-адресу

Модифицированный клиент из раздела 23.7 использовал уведомления в качестве сигнала для получения списков адресов. Это было достаточно удобно, поскольку идентификатор ассоциации, для которой требовалось получить адреса, содержался в уведомлении в поле sac_assoc_id. Но что если приложение не отслеживает идентификаторы ассоциаций, а ему вдруг понадобилось определить какой- либо идентификатор по адресу собеседника? В листинге 23.13 представлена простая функция, преобразующая адрес собеседника в идентификатор ассоциации. Эта функция будет использоваться сервером из раздела 23.10.

Листинг 23.13. Преобразование адреса в идентификатор ассоциации

//sctp/sctp_addr_to_associd.с

 1 #include "unp.h"

 2 sctp_assoc_t

 3 sctp_address_to_associd(int sock_fd, struct sockaddr *sa, socklen_t salen)

 4 {

 5  struct sctp_paddrparams sp;

 6  int siz;

 7  siz = sizeof(struct sctp_paddrparams);

 8  bzero(&sp, siz);

 9  memcpy(&sp, spp_address, sa.salen);

10  sctp_opt_info(sock_fd, 0, SCTP_PEER_ADDR_PARAMS, &sp, &siz);

11  return(sp.spp_assoc_id);

12 }

Инициализация

7-8 Функция начинает работу с инициализации структуры sctp_paddrparams.

Копирование адреса

9 Мы копируем адрес в структуру sctp_paddrparams, используя переданную нам вызвавшим процессом информацию о длине этого адреса.

Вызов параметра сокета

10 При помощи параметра сокета SCTP_PEER_ADDR_PARAMS наша функция запрашивает параметры адреса собеседника. Обратите внимание, что мы используем sctp_opt_info вместо getsockopt, потому что параметр SCTP_PEER_ADDR_PARAMS требует копирования аргументов как в ядро, так и из ядра. Вызов, который мы делаем, возвратит нам текущий интервал проверки работоспособности соединения, максимальное количество попыток повторной передачи перед принятием решения о признании адреса собеседника отказавшим, и, что самое важное, идентификатор ассоциации. Мы не проверяем возвращаемое значение, потому что если вызов оказывается неудачным, мы хотим вернуть 0.

11 Функция возвращает идентификатор ассоциации. Если вызов sctp_opt_info оказался неудачным, обнуление структуры гарантирует, что вызвавший нашу функцию процесс получит 0. Идентификатор ассоциации нулевым быть не может. Это значение используется реализацией SCTP для указания на отсутствие ассоциации.

23.9. Проверка соединения и ошибки доступа

Механизм периодической проверки соединения, предоставляемый протоколом SCTP, основан на той же концепции, что и параметр поддержания соединения TCP keep-alive. Однако в SCTP этот механизм по умолчанию включен, тогда как в TCP он выключен. Приложение может устанавливать пороговое значение количества неудачных проверок при помощи того же параметра сокета, который использовался в разделе 23.8. Порог ошибок — это количество пропущенных проверочных пакетов и тайм-аутов повторной передачи, после которого адрес получателя считается недоступным. Когда доступность адреса восстанавливается (о чем сообщают все те же проверочные пакеты), он снова становится активным.

Приложение может отключить проверку соединения, но без нее SCTP не сможет узнать о доступности адреса собеседника, который ранее был признан недоступным. Без вмешательства пользователя такой адрес не сможет стать активным.

Параметр проверки соединения задается полем spp_hbinterval структуры sctp_paddrparams. Если приложение устанавливает это поле равным SCTP_NO_HB (эта константа имеет значение 0), проверка соединения отключается. Ненулевое значение устанавливает задержку проверки соединения в миллисекундах. К фиксированной задержке прибавляется текущее значение таймера повторной передачи и некоторое случайное число, в результате чего получается реальный промежуток времени между проверками соединения. В листинге 23.14 приводится небольшая функция, которая позволяет устанавливать задержку проверки соединения, или вовсе отключать этот механизм протокола SCTP для конкретного адресата. Обратите внимание, что если поле spp_pathmaxrxr структуры sctp_paddrparams оставить равным нулю, текущее значение задержки останется неизменным.

Листинг 23.14. Управление периодической проверкой соединения

//sctp/sctp_modify_hb.c

 1 #include "unp.h"

 2 int

 3 heartbeat_action(int sock_fd, struct sockaddr *sa, socklen_t salen,

 4 u_int value)

 5 {

 6  struct sctp_paddrparams sp;

 7  int siz;

 8  bzero(&sp, sizeof(sp));

 9  sp.spp_hbinterval = value;

10  memcpy((caddr_t)&sp, spp_address, sa.salen);

11  Setsockopt(sock_fd, IPPROTO_SCTP,

12   SCTP_PEER_ADDR_PARAMS, &sp, sizeof(sp));

13  return(0);

14 }

Обнуление структуры sctp_paddrparams и копирование аргумента

8-9 Мы обнуляем структуру sctp_paddrparams, чтобы случайно не изменить какой-нибудь параметр, который нас не интересует. Затем мы копируем в нее переданное пользователем значение задержки: SCTP_ISSUE_HB, SCTP_NO_HB или конкретное число.

Установка адреса

10 Функция подготавливает адрес и копирует его в структуру sctp_paddrparams, чтобы реализация SCTP знала, к какому адресу относятся устанавливаемые нами параметры периодической проверки соединения.

Выполнение действия

11-12 Наконец, функция делает вызов параметра сокета, чтобы выполнить запрошенную пользователем операцию.

23.10. Выделение ассоциации

Пока что мы занимались исключительно интерфейсом типа «один-ко-многим». Этот интерфейс имеет несколько преимуществ перед традиционным интерфейсом «один-к-одному»:

■ программа работает с единственным дескриптором;

■ программисту достаточно написать простой последовательный сервер;

■ приложение может передавать данные в третьем и четвертом пакетах четырехэтажного рукопожатия, если для неявной установки соединения используются функции sendmsg и sctp_sendmsg;

1 ... 175 176 177 178 179 180 181 182 183 ... 263
Перейти на страницу:
Тут вы можете бесплатно читать книгу UNIX: разработка сетевых приложений - Уильям Стивенс.
Комментарии