UNIX: разработка сетевых приложений
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требует копирования аргументов как в ядро, так и из ядра. Вызов, который мы делаем, возвратит нам текущий интервал проверки работоспособности соединения, максимальное количество попыток повторной передачи перед принятием решения о признании адреса собеседника отказавшим, и, что самое важное, идентификатор ассоциации. Мы не проверяем возвращаемое значение, потому что если вызов оказывается неудачным, мы хотим вернуть 0.SCTP_PEER_ADDR_PARAMSФункция возвращает идентификатор ассоциации. Если вызов11оказался неудачным, обнуление структуры гарантирует, что вызвавший нашу функцию процесс получит 0. Идентификатор ассоциации нулевым быть не может. Это значение используется реализацией SCTP для указания на отсутствие ассоциации.sctp_opt_info23.9. Проверка соединения и ошибки доступа
Механизм периодической проверки соединения, предоставляемый протоколом SCTP, основан на той же концепции, что и параметр поддержания соединения TCP keep-alive. Однако в SCTP этот механизм по умолчанию включен, тогда как в TCP он выключен. Приложение может устанавливать пороговое значение количества неудачных проверок при помощи того же параметра сокета, который использовался в разделе 23.8. Порог ошибок — это количество пропущенных проверочных пакетов и тайм-аутов повторной передачи, после которого адрес получателя считается недоступным. Когда доступность адреса восстанавливается (о чем сообщают все те же проверочные пакеты), он снова становится активным.
Приложение может отключить проверку соединения, но без нее SCTP не сможет узнать о доступности адреса собеседника, который ранее был признан недоступным. Без вмешательства пользователя такой адрес не сможет стать активным.
Параметр проверки соединения задается полем
структурыspp_hbinterval. Если приложение устанавливает это поле равнымsctp_paddrparams(эта константа имеет значение 0), проверка соединения отключается. Ненулевое значение устанавливает задержку проверки соединения в миллисекундах. К фиксированной задержке прибавляется текущее значение таймера повторной передачи и некоторое случайное число, в результате чего получается реальный промежуток времени между проверками соединения. В листинге 23.14 приводится небольшая функция, которая позволяет устанавливать задержку проверки соединения, или вовсе отключать этот механизм протокола SCTP для конкретного адресата. Обратите внимание, что если полеSCTP_NO_HBструктурыspp_pathmaxrxrоставить равным нулю, текущее значение задержки останется неизменным.sctp_paddrparamsЛистинг 23.14. Управление периодической проверкой соединения
//sctp/sctp_modify_hb.c1 #include "unp.h"2 int3 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 знала, к какому адресу относятся устанавливаемые нами параметры периодической проверки соединения.sctp_paddrparamsВыполнение действияНаконец, функция делает вызов параметра сокета, чтобы выполнить запрошенную пользователем операцию.11-1223.10. Выделение ассоциации
Пока что мы занимались исключительно интерфейсом типа «один-ко-многим». Этот интерфейс имеет несколько преимуществ перед традиционным интерфейсом «один-к-одному»:
■ программа работает с единственным дескриптором;
■ программисту достаточно написать простой последовательный сервер;
■ приложение может передавать данные в третьем и четвертом пакетах четырехэтажного рукопожатия, если для неявной установки соединения используются функции
иsendmsg;sctp_sendmsg■ отсутствует необходимость в отслеживании состояния на транспортном уровне. Другими словами, приложение просто запрашивает данные из дескриптора сокета, не вызывая традиционных функций
иconnectдля получения сообщений.acceptЕсть у этого интерфейса и недостатки. Самый существенный из них состоит в том, что интерфейс типа «один-ко-многим» затрудняет написание параллельного сервера (многопоточного или порождающего процессы). Для устранения этого недостатка была придумана функция
. Она принимает в качестве аргумента дескриптор сокета типа «один-ко-многим» и идентификатор ассоциации, а возвращает новый дескриптор сокета типа «один-к-одному» с единственной ассоциацией (сохраняя все уведомления и данные, помещенные в очередь этой ассоциации). Исходный сокет остается открытым, причем все остальные ассоциации проведенной операцией извлечения никак не затрагиваются.sctp_peeloff