/* Протокол 6 (выборочный повтор) принимает фреймы в любом порядке, но передает их сетевому уровню, соблюдая порядок. С каждым неподтвержденным фреймом связан таймер. При срабатывании таймера передается повторно только этот фрейм, а не все неподтвержденные фреймы, как в протоколе 5.
#define MAX_SEQ 7 /* должно быть 2^n-1 */
#define NR_BUFS ((MAX_SEQ + 1)/2)
typedef enum {frame_arrival, cksum_err, timeout, network_layer_ready, ack_timeout} event_type;
#include "protocol.h"
boolean no_nak = true; /* отрицательное подтверждение (nak) еще не посылалось */
seq_nr oldest_frame = MAX_SEQ+1; /* начальное значение для симулятора */
static boolean between(seq_nr a, seq_nr b, seq_nr c)
{
/* То же, что и в протоколе 5, но короче и запутаннее.
return ((a <= b) && (b < c)) || ((c < a) && (a <= b)) || ((b < c) && (c < a));
}
static void send_frame(frame_kind fk, seq_nr frame_nr, seq_nr frame_expected, packet buffer[ ])
{
/* Сформировать и послать данные, а также положительное или отрицательное подтверждение */
frame s; /* временная переменная */
s.kind = fk; /* kind == data, ack или nak */
if (fk == data) s.info = buffer[frame_nr % NR_BUFS];
s.seq = frame_nr; /* имеет значение только для информационных фреймов */
s.ack = (frame_expected + MAX_SEQ) % (MAX_SEQ + 1);
if (fk == nak) no_nak = false; /* один nak на фрейм, пожалуйста */
to_physical_layer(&s); /* передать фрейм */
if (fk == data) start_timer(frame_nr % NR_BUFS);
stop_ack_timer(); /* отдельный фрейм с подтверждением не нужен */
}
void protocol6(void)
{
seq_nr ack_expected; /* нижний край окна отправителя */
seq_nr next_frame_to_send; /* верхний край окна отправителя + 1 */
seq_nr frame_expected; /* нижний край окна получателя */
seq_nr too_far; /* верхний край окна получателя + 1 */
int i; /* индекс массива буферов */
frame r; /* временная переменная */
packet out_buf[NR_BUFS]; /* буферы для исходящего потока */
packet in_buf[NR_BUFS]; /* буферы для входящего потока */
boolean arrived[NR_BUFS]; /* входящая битовая карта */
seq_nr nbuffered; /* количество использующихся в данный момент выходных буферов */
event_type event;
enable_network_layer(); /* инициализация */
ack_expected = 0; /* номер следующего ожидаемого входящего подтверждения */
next_frame_to_send = 0; /* номер следующего посылаемого фрейма */
frame_expected = 0;
too_far = NR_BUFS;
nbuffered = 0; /* вначале буфер пуст */
for (i = 0; i < NR_BUFS; i++) arrived[i] = false;
while (true) {
wait_for_event(&event); /* пять возможных событий: см. event_type выше */
switch(event) {
case network_layer_ready: /* получить, сохранить и передать новый фрейм */
nbuffered = nbuffered + 1; /* увеличить окно отправителя */
from_network_layer(&out_buf[next_frame_to_send % NR_BUFS]); /* получить новый пакет у сетевого уровня */
send_frame(data, next_frame_to_send, frame_expected, out_buf); /* передать фрейм */
inc(next_frame_to_send); /* увеличить верхний край окна отправителя */
break;
case frame_arrival: /* пришел фрейм данных или с подтверждением */
from_physical_layer(&r); /* получить пришедший фрейм у физического уровня */
if (r.kind == data) {
/* Фрейм пришел в целости. */
if ((r.seq != frame_expected) && no_nak)
send_frame(nak, 0, frame_expected, out_buf); else start_ack_timer();
if (between(frame_expected,r.seq,too_far) && (arrived[r.seq%NR_BUFS]==false)) {
/* Фреймы могут приниматься в любом порядке. */