UNIX: разработка сетевых приложений
Шрифт:
21 sctp_freeladdrs(sal);
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
Список адресов передается в упакованном формате. Это не просто массив структур 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
. Копирование адреса
Поделиться с друзьями: