23.3. Частичная доставка

23.3. Частичная доставка

Механизм частичной доставки (partial delivery) используется стеком SCTP каждый раз, когда требуется доставить приложению большое сообщение. Сообщение считается «большим», если SCTP решает, что у него недостаточно ресурсов на его обработку. Частичная доставка накладывает на работу SCTP определенные ограничения:

? объем памяти, занимаемой сообщением в буфере, должен превосходить некоторое пороговое значение;

? доставка может выполняться только последовательно от начала сообщения до первого отсутствующего блока;

? после включения механизма частичной доставки приложение не может получить никакие другие сообщения до тех пор, пока «большое» сообщение не будет им полностью считано из буфера. Таким образом, большое сообщение блокирует все остальные, которые в противном случае могли бы быть доставлены (в том числе и по другим потокам).

В реализации SCTP, выполненной группой KAME, используется пороговое значение, равное половине объема приемного буфера сокета. На момент написания этой книги объем приемного буфера по умолчанию составляет 131 072 байта. Если параметр сокета SO_RCVBUF не меняется, механизм частичной доставки будет включаться только для сообщений, превышающих 65 536 байт. Мы продолжим расширение новой версии сервера из раздела 10.2, написав функцию-обертку для вызова sctp_recvmsg. Затем мы создадим новый сервер, который будет использовать эту функцию. В листинге 23.2 представлена функция-обертка, способная работать с механизмом частичной доставки.

Листинг 23.2. Работа с API частичной доставки

//sctp/sctp_pdapirev.c

 1 #include "unp.h"

 2 static uint8_t *sctp_pdapi_readbuf=NULL;

 3 static int sctp_pdapi_rdbuf_sz=0;

 4 uint8_t*

 5 pdapi_recvmsg(int sock_fd,

 6  int *rdlen,

 7  SA *from,

 8  int *from_len, struct sctp_sndrcvinfo *sri, int *msg_flags)

 9 {

10  int rdsz, left, at_in_buf;

11  int frmlen=0;

12  if (sctp_pdapi_readbuf == NULL) {

13   sctp_pdapi_readbuf = (uint8_t*)Malloc(SCTP_PDAPI_INCR_SZ);

14   sctp_pdapi_rdbuf_sz = SCTP_PDAPI_INCR_SZ;

15  }

16  at_in_buf = Sctp_recvmsg(sock_fd, sctp_pdapi_readbuf, sctp_pdapi_rdbuf_sz,

17   from, from_len,

18   sri.msg_flags);

19  if (at_in_buf < 1) {

20   *rdlen = at_in_buf;

21   return(NULL);

22  }

23  while ((*msg_flags & MSG_EOR) == 0) {

24   left = sctp_pdapi_rdbuf_sz = at_in_buf;

25   if (left < SCTP_PDAPI_NEED_MORE_THRESHOLD) {

26    sctp_pdapi_readbuf =

27     realloc(sctp_pdapi_readbuf,

28      setp_pdapi_rdbuf_sz + SCTP_PDAPI_INCR_SZ);

29    if (sctp_pdapi_readbuf == NULL) {

30     err_quit("sctp_pdapi ran out of memory");

31    }

32    sctp_pdapi_rdbuf_sz += SCTP_PDAPI_INCR_SZ;

33     left = sctp_pdapi_rdbuf_sz - at_in_buf;

34   

35   rdsz = Sctp_recvmsg(sock_fd, &sctp_pdapi_readbuf[at_in_buf],

36    left, NULL, &frmlen, NULL, msg_flags);

37   at_in_buf += rdsz;

38  }

39  *rdlen = at_in_buf;

40  return(sctp_pdapi_readbuf);

41 }

Подготовка статического буфера

12-15 Если статический буфер не выделен, функция выделяет его и инициализирует переменную, хранящую информацию о состоянии этого буфера.

Чтение сообщения

16-18 Первое сообщение считывается из сокета вызовом sctp_recvmsg.

Обработка ошибки чтения

19-22 Если sctp_recvmsg возвращает ошибку или признак конца файла EOF, соответствующий код возвращается вызвавшему нашу функцию процессу без всяких изменений.

Если сообщение считано не полностью

23-24 Если флаги сообщения показывают, что оно было считано не полностью, мы вызываем функцию sctp_recvmsg снова. Предварительно мы вычисляем объем свободного места в буфере.

Проверка необходимости увеличения статического буфера

25-34 Если остаток приемного буфера оказался меньше некоторого минимального значения, этот буфер необходимо увеличить. С этой целью мы вызываем функцию realloc, выделяющую буфер большего размера, после чего копируем в новый буфер данные из старого буфера. Если по какой-то причине размер буфера не может быть увеличен, функция завершает свою работу с выводом сообщения об ошибке.

Получение данных

35-36 Новые данные считываются из буфера вызовом sctp_recvmsg.

Шаг вперед

37-38 Функция увеличивает индекс буфера, после чего возвращается на проверку полного считывания сообщения.

После завершения цикла

39-40 После завершения цикла функция копирует количество считанных байтов в буфер, указатель на который передается ей вызвавшим процессом, и возвращает этому процессу указатель на собственный буфер.

Теперь мы можем изменить сервер SCTP таким образом, чтобы он использовал нашу новую функцию. Новый код представлен в листинге 23.3.

Листинг 23.3. Сервер SCTP, использующий API частичной доставки

//sctp/sctpserv05.c

26 for (;;) {

27  len = sizeof(struct sockaddr_in);

28  bzero(&sri,.sizeof(sri));

29  readbuf = pdapi_recvmsg(sock_fd, &rd_sz,

30   (SA*)&cliaddr, &len, &sri, &msg_flags);

31  if (readbuf == NULL)

32   continue;

Чтение сообщения

29-30 Сервер вызывает новую функцию-обертку интерфейса частичной доставки. Предварительно обнуляется переменная sri.

Проверка наличия считанных данных

31-32 Обратите внимание, что теперь серверу приходится проверять объем буфера, чтобы убедиться, что чтение было успешным. Если буфер оказывается нулевым, программа переходит на начало цикла.

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

Этап 1: Доставка информации и оформления

Из книги Разгони свой сайт автора Мациевский Николай

Этап 1: Доставка информации и оформления На этом этапе разработчики должны сделать все возможное, чтобы не замедлить скорость загрузки страницы. Фактически идет речь об ускорении первой стадии загрузки. Наиболее важными методами здесь является сжатие (gzip) текстовых


Частичная специализация

Из книги Вариации на тему STL. Адаптер обобщенного указателя на функцию-член класса автора Гусаров Михаил

Частичная специализация К сожалению, не все компиляторы поддерживают частичную специализацию шаблонных классов.ПРИМЕЧАНИЕ К таким относится и Microsoft Visual C++ 6.0/7.0 Для решения этой проблемы можно использовать паттерн «traits», специфичный для C++. К сожалению, он не сможет


Частичная специализация по виду аргумента шаблона

Из книги Симуляция частичной специализации автора Кузнецов Павел

Частичная специализация по виду аргумента шаблона Одним из аспектов частичной специализации является возможность специализировать шаблон по виду аргумента, например, предоставить общую для всех указателей специализацию шаблона:template‹class T› class С { //…}; template‹class T› class


Частичная сумма (Partial sum)

Из книги Руководство по стандартной библиотеке шаблонов (STL) автора Ли Менг

Частичная сумма (Partial sum) template ‹class InputIterator, class OutputIterator›OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result);template ‹class InputIterator, class OutputIterator, class BinaryOperation›OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op);partial_sum присваивает каждому итератору i в диапазоне [result,


Доставка почты прерывается сообщением об ошибке

Из книги Компьютер на 100. Начинаем с Windows Vista автора Зозуля Юрий

Доставка почты прерывается сообщением об ошибке Проверьте работоспособность подключения к Интернету, попытавшись загрузить какой-нибудь сайт в Internet Explorer. Посмотрите свойства учетной записи, особое внимание следует обратить на правильность имени пользователя и


17.4.4. Доставка почты

Из книги Самоучитель работы на компьютере автора Колисниченко Денис Николаевич

17.4.4. Доставка почты На панели инструментов (основное окно Outlook Express) есть кнопка Доставить почту. При ее нажатии происходит следующее:проверяется ваш почтовый ящик: если есть новые сообщения, то они загружаются. Непрочитанные сообщения в папке Входящие будут выделены


11.7.2 Доставка запроса от клиента на сервер

Из книги TCP/IP Архитектура, протоколы, реализация (включая IP версии 6 и IP Security) автора Фейт Сидни М

11.7.2 Доставка запроса от клиента на сервер Клиент не имеет сведений об адресе для направления запроса и отправляет его с IP-адресом источника 0.0.0.0 и IP-адресом приемника 255.255.255.255.Сервер (или серверы) в одной с клиентом локальной сети услышит посланный запрос. Если клиент


Доставка товара

Из книги Интернет-шопинг для неопытных пользователей автора Шестопалова Елена

Доставка товара Если вы живете в Москве, то чаще всего доставка осуществляется курьером, в день покупки (если вы сделали заказ в первой половине дня) или на следующий день. Этот способ доставки считается самым удобным. Я живу не в Москве, и меня всегда интересует доставка в


Бесплатная доставка

Из книги Удвоение продаж в интернет-магазине автора Парабеллум Андрей Алексеевич

Бесплатная доставка Это близкий к описанному выше способ манипуляции, при котором вместо скидок нужно предлагать бесплатную доставку выбранных товаров при достижении определенной суммы заказа, при которой цена доставки является


Доставка и обработка сигнала

Из книги Операционная система UNIX автора Робачевский Андрей М.

Доставка и обработка сигнала Для каждого сигнала в системе определена обработка по умолчанию, которую выполняет ядро, если процесс не указал другого действия. В общем случае существуют пять возможных действий: завершить выполнение процесса (с созданием образа core и без),


15.8. Доставка пуш-уведомлений в приложение

Из книги iOS. Приемы программирования автора Нахавандипур Вандад

15.8. Доставка пуш-уведомлений в приложение Постановка задачи Требуется отправлять пуш-уведомления на пользовательские устройства, которые зарегистрированы для получения таких