Получение и вывод локальных адресов
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
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
Список адресов передается в упакованном формате. Это не просто массив структур s ockaddr_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.
Читать дальше
Конец ознакомительного отрывка
Купить книгу