UNIX: разработка сетевых приложений
Шрифт:
68 sre = &snp->sn_remote_error;
69 printf("SCTP_REMOTE_ERROR: assoc=0x%x error=%d\n",
70 (uint32_t)sre->sre_assoc_id, sre->sre_error);
71 break;
72 case SCTP_SEND_FAILED:
73 ssf = &snp->sn_send_failed;
74 printf("SCTP_SEND_FAILED: assoc=0x%x error=%d\n",
75 (uint32_t)ssf->ssf_assoc_id, ssf->ssf_error);
76 break;
77 case SCTP_ADAPTION_INDICATION:
78 ae = &snp->sn_adaption_event;
79 printf("SCTP_ADAPTION_INDICATION: 0x%x\n",
80 (u_int)ae->sai_adaption_ind);
81 break;
82 case SCTP_PARTIAL_DELIVERY_EVENT:
83 pdapi = &snp->sn_pdapi_event;
84 if (pdapi->pdapi_indication == SCTP_PARTIAL_DELIVERY_ABORTED)
85 printf("SCTP_PARTIAL_DELIEVERY_ABORTED\n");
86 else
87 printf("Unknown SCTP_PARTIAL_DELIVERY_EVENT 0x%x\n",
88 pdapi->pdapi_indication);
89 break;
90 case SCTP_SHUTDOWN_EVENT:
91 sse = &snp->sn_shutdown_event;
92 printf("SCTP_SHUTDOWN_EVENT: assoc=0x%x\n",
93 (uint32_t)sse->sse_assoc_id);
94 break;
95 default:
96 printf("Unknown notification event type=0x%x\n",
97 snp->sn_header.sn_type);
98 }
99 }
Преобразование
буфера и начало ветвления
14-15
Функция преобразует буфер вызова к типу union, после чего разыменовывает структуру sn_header
и тип sn_type
и выполняет ветвление по значению соответствующего поля. Обработка изменения состояния ассоциации
16-40
Если функция обнаруживает в буфере уведомление об изменении ассоциации, она выводит тип происшедшего изменения. Изменение адреса собеседника
16-40
Если получено уведомление об изменении адреса собеседника, функция распечатывает событие и новый адрес. Ошибка на удаленном узле
67-71
Если получено уведомление об ошибке на удаленном узле, функция отображает сообщение об этом вместе с идентификатором ассоциации, для которой получено уведомление. Мы не пытаемся декодировать и отобразить сообщение об ошибке, присланное собеседником. При необходимости эти сведения можно получить из поля sre_data
структуры sctp_remote_error
. Ошибка
отправки сообщения
72-76
Если получено уведомление об ошибке отправки сообщения, мы можем сделать вывод, что сообщение не было отправлено собеседнику. Это означает, что либо ассоциация завершает работу и вскоре будет получено уведомление об изменении ее состояния (если оно еще не было получено) или же сервер использует расширение частичной надежности и отправка сообщения оказалась неудачной из-за наложенных ограничений. Данные, которые все-таки были переданы, помещаются в поле ssf_data
, которая наша функция не использует. Индикация уровня адаптера
77-81
Если получено уведомление об уровне адаптера, функция отображает соответствующее 32-разрядное значение, полученное в сообщении INIT или INIT-ACK. Уведомление механизма частичной доставки
82-89
Если получено уведомление механизма частичной доставки, функция выводит на экран соответствующее сообщение. Единственное определенное на момент написания этой книги событие, связанное с частичной доставкой, состоит в ее аварийном завершении. Уведомление о завершении ассоциации
90-94
Если получено уведомление о завершении ассоциации, мы можем сделать вывод, что собеседник выполняет корректное закрытие. За этим уведомлением обычно следует уведомление об изменении состояния ассоциации, которое приходит б момент окончания последовательности пакетов, завершающих ассоциацию. Код сервера, использующего нашу новую функцию, приведен в листинге 23.5. Листинг 23.5. Сервер, обрабатывающий уведомления о событиях
//sctp/sctpserv06.c
21 bzero(&evnts, sizeof(evnts));
22 evnts.sctp_data_io_event = 1;
23 evnts.sctp_association_event = 1;
24 evnts.sctp_address_event = 1;
25 evnts.sctp_send_failure_event = 1;
26 evnts.sctp_peer_error_event = 1;
27 evnts.sctp_shutdown_event = 1;
28 evnts.sctp_partial_delivery_event = 1;
29 evnts.sctp_adaption_layer_event = 1;
30 Setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts));
31 Listen(sock_fd, LISTENQ);
32 for (;;) {
33 len = sizeof(struct sockaddr_in);
34 rd_sz = Sctp_recvmsg(sock_fd, readbuf, sizeof(readbuf),
35 (SA*)&cliaddr, &len, &sri, &msg_flags);
Поделиться с друзьями: