Выделенный сокет может быть передан потоку или дочернему процессу для обработки запросов клиента. Листинг 23.15 демонстрирует новую модифицированную версию сервера, который обрабатывает первое сообщение клиента, выделяет ассоциацию при помощи
sctp_peeloff
, порождает дочерний процесс и вызывает функцию
str_echo
для TCP, которая была написана в разделе 5.3. Адрес из полученного сообщения мы передаем нашей функции из раздела 23.8, которая по этому адресу определяет идентификатор ассоциации. Идентификатор хранится также в поле
sri
,
sinfo_assoc_id
. Наша функция служит лишь иллюстрацией использования альтернативного метода. Породив процесс, сервер переходит к обработке следующего сообщения.
Листинг 23.15. Параллельный сервер SCTP
//sctp/sctpserv_fork.c
23 for (;;) {
24 len = sizeof(struct sockaddr_in);
25 rd_sz = Sctp_recvmsg(sock_fd, readbuf, sizeof(readbuf),
26 (SA*)&cliaddr, &len, &sri, &msg_flags);
27 Sctp_sendmsg(sock_fd, readbuf, rd_sz,
28 (SA*)&cliaddr, len,
29 sri.sinfo_ppid,
30 sri.sinfo_flags, sn.sinfo_stream, 0, 0);
31 assoc = sctp_address_to_associd(sock_fd, (SA*)&cliaddr, len);
32 if ((int)assoc == 0) {
33 err_ret("Can't get association id");
34 continue;
35 }
36 connfd = sctp_peeloff(sock_fd, assoc);
37 if (connfd == -1) {
38 err_ret("sctp_peeloff fails");
39 continue;
40 }
41 if ((childpid = fork()) == 0) {
42 Close(sock_fd);
43 str_echo(connfd);
44 exit(0);
45 } else {
46 Close(connfd);
47 }
48 }
Получение и обработка первого сообщения
26-30
Сервер получает и обрабатывает первое сообщение клиента.
Преобразование адреса в идентификатор ассоциации
31-35
Сервер вызывает функцию из листинга 23.13 для получения идентификатора ассоциации по ее адресу. Если что-то мешает серверу получить идентификатор, он не делает попыток породить дочерний процесс, а просто переходит к обработке следующего сообщения.
Выделение ассоциации
36-40
Сервер выделяет ассоциацию в отдельный дескриптор сокета при помощи
sctp_peeloff
. Полученный сокет типа «один-к-одному» может быть без проблем передан написанной ранее для TCP функции
str_echo
.
Передача работы дочернему процессу
41-47
Сервер порождает дочерний процесс, который и выполняет всю обработку по конкретному дескриптору.
23.11. Управление таймерами
Протокол SCTP имеет множество численных пользовательских параметров. Все они устанавливаются через параметры сокетов, рассмотренные в разделе 7.10. Далее мы займемся рассмотрением нескольких параметров, определяющих задержку перед объявлением об отказе ассоциации или адреса собеседника.
Время обнаружения отказа в SCTP определяется семью переменными (табл. 23.1).
Таблица 23.1. Поля таймеров SCTP
Поле | Описание | По умолчанию | Единицы |
srto_min | Минимальный тайм-аут повторной передачи | 1000 | Мс |
srto_max | Максимальный тайм-аут повторной передачи | 60000 | Мс |
srto_initial | Начальный тайм-аут повторной передачи | 3000 | Мс |
sinit_max_init_timeo | Максимальный тайм-аут повторной передачи сегмента INIT | 3000 | Мс |
sinit_max_attempts | Максимальное количество повторных передач сегмента INIT | 8 | попыток |
spp_pathmaxrxt | Максимальное количество повторных передач по адресу | 5 | попыток |
sasoc_asocmaxrxt | Максимальное количество повторных передач на ассоциацию | 10 | попыток |
Эти параметры можно воспринимать как регуляторы, укорачивающие и удлиняющие время обнаружения отказа. Рассмотрим два сценария.
1. Конечная точка SCTP пытается открыть ассоциацию с собеседником, отключившимся от сети.
2. Две многоинтерфейсные конечные точки SCTP обмениваются данными. Одна из них отключается от сети питания в момент передачи данных. Сообщения ICMP фильтруются защитными экранами и потому не достигают второй конечной точки.
В сценарии 1 система, пытающаяся открыть соединение, устанавливает таймер RTO равным
srto_initial
(3000 мс). После первой повторной передачи пакета INIT таймер устанавливается на значение 6000 мс. Это продолжается до тех пор, пока не будет сделано
sinit_max_attempts
попыток (9 штук), между которыми пройдут семь тайм-аутов. Удвоение таймера закончится на величине
sinit_max_init_timeo
, равной 60 000 мс. Таким образом, через 3 + 6 + 12 + 24 + 48 + 60 + 60 + 60 = 273 с стек SCTP объявит потенциального собеседника недоступным.
Вращением нескольких «ручек» мы можем удлинять и укорачивать это время. Начнем с двух параметров, позволяющих уменьшить общую задержку. Сократим количество повторных передач, изменив переменную
sinit_max_attempts
. Альтернативное изменение может состоять в уменьшении максимального тайм- аута для пакета INIT (переменная
srto_max_init_timeo
). Если количество попыток снизить до 4, время детектирования резко упадет до 45 с (одна шестая первоначального значения). Однако у этого метода есть недостаток: из-за проблем в сети или перегруженности собеседника мы можем объявить его недоступным, даже если это состояние является лишь временным.