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
Обратите внимание, что теперь серверу приходится проверять объем буфера, чтобы убедиться, что чтение было успешным. Если буфер оказывается нулевым, программа переходит на начало цикла.
23.4. Уведомления
В разделе 9.14 уже отмечалось, что приложение может подписаться на уведомления, общее количество которых составляет 7 штук. Пока что наше приложение игнорировало все события, за исключением прихода новых данных. В этом разделе приводятся примеры приема и интерпретации уведомлений SCTP о других событиях транспортного уровня. В листинге 23.4 представлена функция, отображающая все получаемые уведомления. Нам придется изменить и код сервера, чтобы разрешить доставку уведомлений обо всех происходящих событиях. Однако сервер не будет использовать получаемые уведомления для чего-либо конкретного.
Листинг 23.4. Функция вывода уведомлений
1 #include "unp.h"
2 void
3 print_notification(char *notify_buf)
4 {
5 union sctp_notification *snp;
6 struct sctp_assoc_change *sac;
7 struct sctp_paddr_change *spc;
8 struct sctp_remote_error *sre;
9 struct sctp_send_failed *ssf;
10 struct sctp_shutdown_event *sse;
11 struct sctp_adaption_event *ae;
12 struct sctp_pdapi_event *pdapi,
13 const char *str;
14 snp = (union sctp_notification*)notify_buf;
15 switch (snp->sn_header.sn_type) {
16 case SCTP_ASSOC_CHANGE:
17 sac = &snp->sn_assoc_change;
18 switch (sac->sac_state) {
19 case SCTP_COMM_UP:
20 str = "COMMUNICATION UP";
21 break;
22 case SCTP_COMM_LOST:
23 str = "COMMUNICATION LOST";
24 break;
25 case SCTP_RESTART:
26 str = "RESTART";
27 break;
28 case SCTP_SHUTDOWN_COMP:
29 str = "SHUTDOWN COMPLETE";
30 break;
31 case SCTP_CANT_STR_ASSOC:
32 str = "CAN'T START ASSOC";
33 break;
34 default:
35 str = "UNKNOWN";
36 break;
37 } /* конец ветвления switch (sac->sac_state) */
38 printf("SCTP_ASSOC_CHANGE %s, assoc=0x%x\n", str,
39 (uint32_t)sac->sac_assoc_id);
40 break;
41 case SCTP_PEER_ADDR_CHANGE:
42 spc = &snp->sn_paddr_change;
43 switch (spc->spc_state) {
44 case SCTP_ADDR_AVAILABLE:
45 str = "ADDRESS AVAILABLE";
46 break;