22   }

23  }

24 }

Проверка типа уведомления

9-13 Функция преобразует буфер приема к типу универсального указателя на уведомления, чтобы определить тип полученного уведомления. Из всех уведомлений нас интересуют только уведомления об изменении ассоциации, а из них — уведомления о создании или перезапуске ассоциации (SCTP_COMM_UP и SCTP_RESTART). Все прочие уведомления нас не интересуют.

Получение и вывод адресов собеседника

14-17 Функция sctp_getpaddrs возвращает нам список удаленных адресов, которые мы выводим при помощи функции sctp_print_addresses, представленной в листинге 23.12. После работы с ней мы освобождаем ресурсы, выделенные sctp_getpaddrs, вызывая функцию sctp_freepaddrs.

Получение и вывод локальных адресов

18-21 Функция sctp_getladdrs возвращает нам список локальных адресов, которые мы выводим на экран вместе с их общим количеством. После завершения работы с адресами мы освобождаем память вызовом sctp_freeladdrs.

Последняя из новых функций называется 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("%s\n", 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: <b>./sctpclient01 10.1.1.5</b>

<b>[0]Hi</b>

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

<b>Control-D</b>

FreeBSD-lap:

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

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

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

//sctp/sctp_addr_to_associd.с

 1 #include &quot;unp.h&quot;

 2 sctp_assoc_t

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


Перейти на страницу:
Изменить размер шрифта: