UNIX: разработка сетевых приложений
Рис. 9.1. Временная диаграмма для сокета SCTP типа «один-к-одному»
Сокет SCTP типа «один-к-одному» является IP-сокетом (семейство
илиAF_INET) со значением типаAF_INET6и значением протоколаSOCK_STREAM.IPPROTO_SCTPСокет типа «один-ко-многим»
Сокет типа «один-ко-многим» дает разработчику приложения возможность написать сервер, не использующий большого количества дескрипторов сокетов. Один дескриптор для такого сервера будет представлять несколько ассоциаций, подобно сокету UDP, способному принимать дейтаграммы от множества клиентов. Для обращения к конкретной ассоциации, установленной для сокета типа «один-ко-многим», используется идентификатор. Идентификатор ассоциации представляет собой значение типа
(обычно это целое число). Значение идентификатора скрывается от приложения, то есть оно не должно использовать идентификатор, если тот еще не был предоставлен приложению ядром.sctp_assoc_tПри написании приложения, использующего сокеты данного типа, рекомендуется помнить о следующих важных моментах:
1. Когда клиент закрывает ассоциацию, она автоматически закрывается и на стороне сервера. При этом удаляются все сведения о состоянии ассоциации в ядре.
2. Только при использовании типа «один-ко-многим» возможна передача данных в третьем и четвертом пакетах четырехэтапного рукопожатия (см. упражнение 9.3).
3. Вызов
,sendtoилиsendmsgдля адресата, с которым еще не установлена ассоциация, приведет к попытке активного открытия, в результате чего будет создана новая ассоциация с указанным адресом. Это происходит даже в том случае, если приложение, вызвавшееsctp_sendmsg, перед этим вызвало для того же сокета функциюsend, запросив пассивное открытие.listen4. Приложение должно использовать функции
,sendtoиsendmsg, но неsctp_sendmsgиsend. (Если вы создали сокет типа «один-к-одному» вызовомwrite, тоsctp_peeloffиsendвызывать можно.)write5. При вызове одной из функций отправки данных используется основной адрес получателя, выбранный системой в момент установки ассоциации (раздел 2.8), если вызывающий процесс не установит флаг
в структуреMSG_ADDR_OVER. Для этого необходимо вызвать функциюsctp_sndrcvinfoс вспомогательными данными или воспользоваться функциейsendmsg.sctp_sendmsg6. Уведомление о событиях для ассоциации может быть включено по умолчанию, так что если приложению не требуется получать эти уведомления, оно должно явным образом отключить их при помощи параметра сокета
. (Одно из множества уведомлений SCTP обсуждается в разделе 9.14.) По умолчанию единственным включенным событием являетсяSCTP_EVENTS. Уведомление о нем передается в виде вспомогательных данных при вызовеsctp_data_io_eventиrecvmsg. Это относится к сокетам обоих типов.sctp_recvmsgПРИМЕЧАНИЕКогда интерфейс API сокетов SCTP находился на стадии разработки, для сокетов типа «один-ко-многим» по умолчанию было включено еще и уведомление об установке ассоциации. В более поздних версиях документации API говорится о том, что по умолчанию для сокетов обоих типов отключены все уведомления, за исключением sctp_data_io_event. Однако не все реализации могут соответствовать этому утверждению. Хорошим тоном будет включать все нужные уведомления и отключать ненужные в явном виде. Благодаря этому разработчик получает гарантию того, что приложение будет вести себя так, как он этого хочет, в любой операционной системе.
Типичная временная диаграмма для сокета типа «один-ко-многим» приведена на рис. 9.2. Сначала запускается сервер, который создает сокет, привязывает его к адресу, вызывает функцию
для того, чтобы разрешить клиентам устанавливать ассоциации, после чего он вызываетlistenи приостанавливается в ожидании первого сообщения. В свою очередь, клиент открывает сокет и вызывает функциюsctp_recvmsg, которая неявно инициирует ассоциацию и вкладывает данные в третий пакет четырехэтапного рукопожатия. Сервер получает запрос, обрабатывает его и отсылает свой ответ. Клиент получает ответ сервера и закрывает сокет, тем самым закрывая и ассоциацию. Сервер переходит к ожиданию следующего сообщения.sctp_sendtoРис. 9.2. Временная диаграмма работы сокета типа «один-ко-многим»
В этом примере рассматривается последовательный сервер, один программный поток которого обрабатывает сообщения, полученные через несколько ассоциаций. SCTP позволяет использовать сокет типа «один-ко-многим» с функцией
(см. раздел 9.12) для реализации комбинированной параллельно- последовательной модели сервера.sctp_peeloff1. Функция
позволяет выделить конкретную ассоциацию (например, долговременный сеанс связи) из сокета типа «один-ко-многим» в отдельный сокет типа «один-к-одному».sctp_peeloff2. Полученный таким образом сокет типа «один-к-одному» может быть передан новому потоку или порожденному процессу (как в модели параллельного сервера).
3. Основной поток обрабатывает сообщения от всех остальных ассоциаций в последовательном режиме.
Сокет SCTP типа «один-ко-многим» является IP-сокетом (семейство
илиAF_INET) со значением типаAF_INET6и значением протоколаSOCK_SEQPACKET.IPPROTO_SCTP9.3. Функция sctp_bindx
Сервер SCTP может привязаться к некоторому подмножеству IP-адресов узла, на котором он запущен. Серверы TCP и UDP могли привязываться либо к одному, либо ко всем адресам узла, но не могли указывать конкретный набор адресов. Функция
делает программирование приложений более гибким, предоставляя возможность связывать сокет SCTP с заданными адресами.sctp_bindx#include <netinet/sctp.h>int sctp_bindx(int <i>sockfd</i>, const struct sockaddr *<i>addrs</i>, int <i>addrcnt</i>, int <i>flags</i>);<i>Возвращает: 0 в случае успешного завершения, -1 в случае ошибки</i>Аргумент
представляет собой дескриптор сокета, возвращаемый функциейsockfd. Второй аргумент — указатель на упакованный список адресов. Каждая структура адреса сокета помещается в буфер непосредственно после предшествующей структуры, без всяких дополняющих нулей (пример приводится на рис. 9.3).socket

