Чтение онлайн

ЖАНРЫ

UNIX: разработка сетевых приложений
Шрифт:

4. Приложение должно использовать функции

sendto
,
sendmsg
и
sctp_sendmsg
, но не
send
и
write
. (Если вы создали сокет типа «один-к-одному» вызовом
sctp_peeloff
, то
send
и
write
вызывать можно.)

5. При вызове одной из функций отправки данных используется основной адрес получателя, выбранный системой в момент установки ассоциации (раздел 2.8), если вызывающий процесс не установит флаг

MSG_ADDR_OVER
в структуре
sctp_sndrcvinfo
. Для этого необходимо вызвать функцию
sendmsg
с вспомогательными
данными или воспользоваться функцией
sctp_sendmsg
.

6. Уведомление о событиях для ассоциации может быть включено по умолчанию, так что если приложению не требуется получать эти уведомления, оно должно явным образом отключить их при помощи параметра сокета

SCTP_EVENTS
. (Одно из множества уведомлений SCTP обсуждается в разделе 9.14.) По умолчанию единственным включенным событием является
sctp_data_io_event
. Уведомление о нем передается в виде вспомогательных данных при вызове
recvmsg
и
sctp_recvmsg
. Это относится к сокетам обоих типов.

ПРИМЕЧАНИЕ

Когда интерфейс API сокетов SCTP находился на стадии разработки, для сокетов типа «один-ко-многим» по умолчанию было включено еще и уведомление об установке ассоциации. В более поздних версиях документации API говорится о том, что по умолчанию для сокетов обоих типов отключены все уведомления, за исключением sctp_data_io_event. Однако не все реализации могут соответствовать этому утверждению. Хорошим тоном будет включать все нужные уведомления и отключать ненужные в явном виде. Благодаря этому разработчик получает гарантию того, что приложение будет вести себя так, как он этого хочет, в любой операционной системе.

Типичная временная диаграмма для сокета типа «один-ко-многим» приведена на рис. 9.2. Сначала запускается сервер, который создает сокет, привязывает его к адресу, вызывает функцию

listen
для того, чтобы разрешить клиентам устанавливать ассоциации, после чего он вызывает
sctp_recvmsg
и приостанавливается в ожидании первого сообщения. В свою очередь, клиент открывает сокет и вызывает функцию
sctp_sendto
, которая неявно инициирует ассоциацию и вкладывает данные в третий пакет четырехэтапного рукопожатия. Сервер получает запрос, обрабатывает его и отсылает свой ответ. Клиент получает ответ сервера и закрывает сокет, тем самым закрывая и ассоциацию. Сервер переходит к ожиданию следующего сообщения.

Рис. 9.2. Временная диаграмма работы сокета типа «один-ко-многим»

В этом примере рассматривается последовательный сервер, один программный поток которого обрабатывает сообщения, полученные через несколько ассоциаций. SCTP позволяет использовать сокет типа «один-ко-многим» с функцией

sctp_peeloff
(см. раздел 9.12) для реализации комбинированной параллельно- последовательной модели сервера.

1. Функция

sctp_peeloff
позволяет выделить конкретную ассоциацию (например, долговременный сеанс связи) из сокета типа «один-ко-многим» в отдельный сокет типа «один-к-одному».

2. Полученный таким образом сокет типа «один-к-одному» может быть передан новому потоку или порожденному процессу (как в модели параллельного сервера).

3. Основной поток обрабатывает сообщения от всех остальных ассоциаций в последовательном режиме.

Сокет SCTP типа «один-ко-многим» является IP-сокетом (семейство

AF_INET
или
AF_INET6
) со значением типа
SOCK_SEQPACKET
и значением протокола
IPPROTO_SCTP
.

9.3. Функция sctp_bindx

Сервер SCTP может привязаться к некоторому подмножеству IP-адресов узла, на котором он запущен. Серверы TCP и UDP могли привязываться либо к одному, либо ко всем

адресам узла, но не могли указывать конкретный набор адресов. Функция
sctp_bindx
делает программирование приложений более гибким, предоставляя возможность связывать сокет SCTP с заданными адресами.

#include <netinet/sctp.h>

int sctp_bindx(int sockfd, const struct sockaddr * addrs, int addrcnt, int flags);

Возвращает: 0 в случае успешного завершения, -1 в случае ошибки

Аргумент

sockfd
представляет собой дескриптор сокета, возвращаемый функцией
socket
. Второй аргумент — указатель на упакованный список адресов. Каждая структура адреса сокета помещается в буфер непосредственно после предшествующей структуры, без всяких дополняющих нулей (пример приводится на рис. 9.3).

Рис. 9.3. Формат упакованного списка адресов для функций SCTP

Количество адресов, передаваемых

sctp_bindx
, указывается в параметре
addrcnt
. Параметр
flags
сообщает функции
sctp_bindx
о необходимости выполнения действий, перечисленных в табл. 9.1.

Таблица 9.1. Флаги функции sctp_bindx

Значение аргумента flags Описание
SCTP_BINDX_ADD_ADDR Добавляет адреса к уже определенным для сокета
SCTP_BINDX_REM_ADDR Удаляет адреса из списка адресов сокета

Функцию

sctp_bindx
можно вызывать независимо от того, привязан ли сокет к каким-нибудь адресам. Для несвязанного сокета вызов
sctp_bindx
приведет к привязке указанного набора адресов. При работе с уже связанным сокетом указание флага
SCTP_BINDX_ADD_ADDR
позволяет добавить адреса к данному дескриптору. Флаг SCTP_BINDX_
REM
_ADDR предназначен для удаления адресов из списка связанных с данным дескриптором. Если
sctp_bindx
вызывается для прослушиваемого сокета, новая конфигурация будет использоваться только для новых ассоциаций; вызов никак не затронет уже установленные ассоциации. Флаги
sctp_bindx
взаимно исключают друг друга: если указать оба, функция вернет ошибку
EINVAL
. Номер порта во всех структурах адреса сокета должен быть одним и тем же. Он должен совпадать с тем номером порта, который был связан с данным сокетом ранее. В противном случае
sctp_bindx
тоже вернет ошибку
EINVAL
.

Если конечная точка поддерживает динамическую адресацию, вызов sctp_bindx с флагом

SCTP_BINDX_REM_ADDR
или
SCTP_BINDX_ADD_ADDR
приведет к передаче собеседнику сообщения о необходимости изменения списка адресов. Поскольку изменение списка адресов для установленной ассоциации не является обязательным, реализации, не поддерживающие эту функцию, будут при попытке ее использования возвращать ошибку
EOPNOTSUPP
. Обратите внимание, что для нормальной работы динамической адресации она должна поддерживаться обеими сторонами. Все это полезно в том случае, если система поддерживает динамическое предоставление интерфейсов: когда открывается доступ к новому интерфейсу Ethernet, приложение может вызвать
SCTP_BINDX_ADD_ADDR
и начать работать с этим интерфейсом по уже установленным ассоциациям.

Поделиться с друзьями: