Чтение онлайн

на главную - закладки

Жанры

UNIX: разработка сетевых приложений
Шрифт:

Пример

Свяжем теперь всю эту информацию воедино в примере. Мы начнем с функции

main
нашего клиента UDP, представленного в листинге 8.3, и изменим в ней только номер порта с
SERV_PORT
на 7 (стандартный эхо-сервер, см. табл. 2.1).

В листинге 22.4 показана функция

dg_cli
. Единственное изменение по сравнению с листингом 8.4 состоит в замене вызовов функций
sendto
и
recvfrom
вызовом нашей новой функции
dg_send_recv
.

Перед

тем как представить функцию
dg_send_recv
и наши функции RTT, которые она вызывает, мы показываем в листинге 22.5 нашу схему реализации функциональных свойств, повышающих надежность клиента UDP. Все функции, имена которых начинаются с
rtt_
, описаны далее.

Листинг 22.4. Функция dg_cli, вызывающая нашу функцию dg_send_recv

//rtt/dg_cli.c

1 #include "unp.h"

2 ssize_t Dg_send_recv(int, const void*, size_t, void*, size_t,

3 const SA*, socklen_t);

4 void

5 dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)

6 {

7 ssize_t n;

8 char sendline[MAXLINE], recvline[MAXLINE + 1];

9 while (Fgets(sendline, MAXLINE, fp) != NULL) {

10 n = Dg_send_recv(sockfd, sendline, strlen(sendline),

11 recvline, MAXLINE, pservaddr, servlen);

12 recvline[n] = 0; /* завершающий нуль */

13 Fputs(recvline, stdout);

14 }

15 }

Листинг 22.5. Схема функций RTT и последовательность их вызова

static sigjmp_buf jmpbuf;

{

формирование запроса

signal(SIGALRM, sig_alrm); /* устанавливаем обработчик сигнала */

rtt_newpack; /* инициализируем значение счетчика rexmt нулем */

sendagain:

sendto;

alarm(rtt_start); /* задаем аргумент функции alarm равным RTO */

if (sigsetjmp(jmpbuf, 1) != 0) {

if (rtt_timeout) /* удваиваем RTO, обновляем оценочные значения */

отказываемся от дальнейших попыток

goto sendagain; /* повторная передача */

}

do {

recvfrom;

} while (неправильный
порядковый номер);

alarm(0); /* отключаем сигнал alarm */

rtt_stop; /* вычисляем RTT и обновляем оценочные значения */

обрабатываем ответ

}

void sig_alrm(int signo) {

siglongjmp(jmpbuf, 1);

}

Если приходит ответ, но его порядковый номер отличается от предполагаемого, мы снова вызываем функцию

recvfrom
, но не отправляем снова тот же запрос и не перезапускаем работающий таймер повторной передачи. Обратите внимание, что в крайнем правом случае на рис. 22.2 последний ответ, полученный на отправленный повторно запрос, будет находиться в приемном буфере сокета до тех пор, пока клиент не решит отправить следующий запрос (и получить на него ответ). Это нормально, поскольку клиент прочитает этот ответ, отметит, что порядковый номер отличается от предполагаемого, проигнорирует ответ и снова вызовет функцию
recvfrom
.

Мы вызываем функции

sigsetjmp
и
siglongjmp
, чтобы предотвратить возникновение ситуации гонок с сигналом
SIGALRM
, который мы описали в разделе 20.5. В листинге 22.6 показана первая часть нашей функции
dg_send_recv
.

Листинг 22.6. Функция dg_send_recv: первая половина

//rtt/dg_send_recv.c

1 #include "unprtt.h"

2 #include <setjmp.h>

3 #define RTT_DEBUG

4 static struct rtt_info rttinfo;

5 static int rttinit = 0;

6 static struct msghdr msgsend, msgrecv;

/* предполагается, что обе структуры инициализированы нулем */

7 static struct hdr {

8 uint32_t seq; /* порядковый номер */

9 uint32_t ts; /* отметка времени при отправке */

10 } sendhdr, recvhdr;

11 static void signalrm(int signo);

12 static sigjmp_buf jmpbuf;

13 ssize_t

14 dg_send_recv(int fd, const void *outbuff, size_t outbytes,

15 void *inbuff, size_t inbytes,

16 const SA *destaddr, socklen_t destlen)

17 {

18 ssize_t n;

Поделиться:
Популярные книги

Курсант: Назад в СССР 10

Дамиров Рафаэль
10. Курсант
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Курсант: Назад в СССР 10

Сумеречный Стрелок 2

Карелин Сергей Витальевич
2. Сумеречный стрелок
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Сумеречный Стрелок 2

Идеальный мир для Лекаря 6

Сапфир Олег
6. Лекарь
Фантастика:
фэнтези
юмористическая фантастика
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 6

Новик

Ланцов Михаил Алексеевич
2. Помещик
Фантастика:
альтернативная история
6.67
рейтинг книги
Новик

На границе империй. Том 9. Часть 3

INDIGO
16. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 3

Метатель

Тарасов Ник
1. Метатель
Фантастика:
боевая фантастика
попаданцы
рпг
фэнтези
фантастика: прочее
постапокалипсис
5.00
рейтинг книги
Метатель

Идеальный мир для Лекаря 23

Сапфир Олег
23. Лекарь
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Идеальный мир для Лекаря 23

Кротовский, вы сдурели

Парсиев Дмитрий
4. РОС: Изнанка Империи
Фантастика:
попаданцы
альтернативная история
рпг
5.00
рейтинг книги
Кротовский, вы сдурели

Книга 5. Империя на марше

Тамбовский Сергей
5. Империя у края
Фантастика:
альтернативная история
5.00
рейтинг книги
Книга 5. Империя на марше

Книга пятая: Древний

Злобин Михаил
5. О чем молчат могилы
Фантастика:
фэнтези
городское фэнтези
мистика
7.68
рейтинг книги
Книга пятая: Древний

Идеальный мир для Лекаря 17

Сапфир Олег
17. Лекарь
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 17

Ну привет, заучка...

Зайцева Мария
Любовные романы:
эро литература
короткие любовные романы
8.30
рейтинг книги
Ну привет, заучка...

Ваше Сиятельство 3

Моури Эрли
3. Ваше Сиятельство
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Ваше Сиятельство 3

Последний попаданец 8

Зубов Константин
8. Последний попаданец
Фантастика:
юмористическая фантастика
рпг
5.00
рейтинг книги
Последний попаданец 8