Шрифт:
В реализации 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
снова. Предварительно мы вычисляем объем свободного места в буфере.