Компьютерные сети. 6-е изд.
вернуться

Д. Таненбаум Э. С., Фимстер Н. , Уэзеролл

Шрифт:

Причина неудачи в том, что при сдвиге окна получателя новый интервал допустимых номеров фреймов перекрыл старый. Соответственно, присылаемый набор фреймов может содержать как новые фреймы (если все подтверждения были получены), так и повторно высланные старые (если подтверждения были потеряны). У принимающей стороны нет возможности отличить их.

Чтобы решить эту проблему, нужно убедиться, что в сдвинутом положении окно не перекроет исходное окно. Размер окна не должен превышать половины от количества порядковых номеров, как показано на илл. 3.22 (в) и 3.22 (г). Например, если для порядковых номеров используются 3 бита, они должны изменяться в пределах от 0 до 7. В таком случае в любой момент времени только четыре фрейма могут быть неподтвержденными. Таким образом, если будут получены фреймы с 0-го по 3-й и будет передвинуто окно для приема фреймов с 4-го по 7-й, получатель сможет безошибочно отличить повторную передачу (фреймы с 0-го по 3-й) от новых фреймов (с 4-го по 7-й). Поэтому в протоколе 6 применяется окно размером (MAX_SEQ + 1)/2.

Возникает новый вопрос: сколько буферов должно быть у получателя? Ни при каких условиях он не должен принимать фреймы, номера которых не попадают в окно. Поэтому количество необходимых буферов равно размеру окна, а не диапазону порядковых номеров. В приведенном выше примере 3-битных номеров требуется четыре буфера с номерами от 0 до 3. Когда приходит фрейм i, он помещается в буфер i mod 4. Обратите внимание, что хотя i и (i + 4), взятые по модулю 4, «соревнуются» за один и тот же буфер, они никогда не оказываются в одном окне одновременно, потому что это привело бы к увеличению размера окна по крайней мере до 5.

/* Протокол 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;

  • Читать дальше
  • 1
  • ...
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • ...

Private-Bookers - русскоязычная библиотека для чтения онлайн. Здесь удобно открывать книги с телефона и ПК, возвращаться к сохраненной странице и держать любимые произведения под рукой. Материалы добавляются пользователями; если считаете, что ваши права нарушены, воспользуйтесь формой обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • help@private-bookers.win