Download as pdf or txt
Download as pdf or txt
You are on page 1of 29

Osnovni protokoli sloja veze

podataka
Definicije funkcija za protokole koji slede
#define MAX_PKT 1024 /* Odredjuje veličinu paketa u bajtovima */

typedef unsigned int seq_nr; /* redni broj ili broj potvrde */


typedef struct {unsigned char data[MAX_PKT];} packet; /* definicija paketa */
typedef enum {data, ack, nak} frame_kind;

typedef struct {
frame_kind kind; /* vrsta ovog okvira*/
seq_nr seq; /* redni broj */
seq_nr ack; /* broj potvrde */
packet info; /* paket mržnog sloja */
} frame;

/* Čekaj da se nešto dogodi; upiši tip dogadjaja u promenljivu event*/


void wait_for_event(event_type *event);

/* Uzmi iz mrežnog sloja paket za prenos*/


void from_network_layer(packet *p);

/* Podatke iz dolaznog okvira isporuči mrežnom sloju */


void to_network_layer(packet *p);
/* Preuzmi dolazni okvir iz fizičkog sloja i kopiraj ga u r */
void from_physical_layer(frame *r);

/* Prosledi fizičkom sloju okvir za slanje */


void to_physical_layer(frame *s);

/* Pokreni sat i omogući dogodjaj timeout */


void start_timer(seq_nr k);

/* Zaustavi sat i onemogući dogadjaj timeout */


void stop_timer(seq_nr k);

/* Omogući mrežnom sloju da izazove dogadjaj network_layer_ready */


void enable_network_layer(void);

/* Zabrani mrežnom sloju da izazove dogadjaj network_layer_ready */


void disable_network_layer(void);

/* Macro inc : ciklično uvećava k za jedinicu */


#define inc(k) if (k < MAX_SEQ) k = k + 1; else k = 0
Protokol 1
neograničen jednosmeran prenos
Pretpostavke:

• Podaci se prenose samo u jednom smeru


• Mrežni slojevi su uvek spremni i na izvorištu i na
odredištu
• Vreme obrade je zanemarljivo
• Baferi su neograničene veličine
• Komunikacioni kanal ne gubi okvire
Protokol 1
neograničen jednosmeran prenos
typedef enum {frame_arrival} event_type;
#include "protocol.h"
void sender1(void) void receiver1(void)
{ {
frame s; frame r;
packet buffer; event_type event;
while (true) while (true)
{ from_network_layer(&b { wait_for_event(&ev
uffer); ent);
s.info = buffer; from_physical_layer(&r);
to_physical_layer(&s);
to_network_layer(&r.info);
}
}
}
}
Protokol 2
jednosmerni protokol ”stani i čekaj”
Pretpostavke:
• Podaci se prenose samo u jednom smeru
• Mrežni slojevi su uvek spremni i na izvorištu i na
odredištu
• Podaci se obradjuju ograničenom brzinom
• Baferi su ograničenog kapaciteta
• Komunikacioni kanal ne gubi okvire

Zadatak protokola je da spreči pošiljaoca da zatrpa


primaoca podacima koje on ne stiže da obradi
Protokol 2
jednosmerni protokol ”stani i čekaj”
typedef enum {frame_arrival} event_type;
#include "protocol.h"
void sender2(void) void receiver2(void)
{ {
frame s; frame r, s;
packet buffer; event_type event;
event_type event; while (true) {
while (true) { wait_for_event(&event);
from_physical_layer(&r);
from_network_layer(&buffer);
to_network_layer(&r.info);
s.info = buffer; to_physical_layer(&s);
to_physical_layer(&s); }
wait_for_event(&event); }
}
}
Protokol 3
jednosmerni protokol na bučnim kanalima
• Ukoliko se okvir ošteti prilikom slanja,
poslaćemo ga ponovo!
• Šta se dešava ako se potvrda ošteti?
• Odgovor: koristiti tajmer i numerisati pakete
• Dovoljno je koristiti jedan bit za numerisanje
paketa
#define MAX_SEQ 1
typedef enum {frame_arrival, cksum_err, timeout}
event_type;
#include "protocol.h"
void sender3(void)
{
seq_nr next_frame_to_send; /* redni broj sledećeg okvira koji se šalje */
frame s;
packet buffer; /* bafer za pakete koji se šalju*/
event_type event;

next_frame_to_send = 0; /* inicijalizacija brojeva odlaznih paketa*/


from_network_layer(&buffer); /* uzmi prvi paket */
while (true) {
s.info = buffer; /* napravi okvir za prenošenje*/
s.seq = next_frame_to_send; /* unesi redni broj u okvir*/
to_physical_layer(&s); /* pošalji okvir*/
start_timer(s.seq); /* ako potvrda ne stigne na vreme, isključi se */
wait_for_event(&event); /* frame_arrival, cksum_err, timeout */
if (event == frame_arrival) {
from_physical_layer(&s); /* uzmi potvrdu */
if (s.ack == next_frame_to_send) {
from_network_layer(&buffer); /* uzmi sledeći okvir za slanje*/
inc(next_frame_to_send); /* predji na sledeći redni broj */
}
}
}
}
void receiver3(void)
{
seq_nr frame_expected;
frame r, s;
event_type event;

frame_expected = 0;
while (true) {
wait_for_event(&event); /* mogućnosti: frame_arrival,cksum_err */
if (event == frame_arrival) { /* stigao je ispravan okvir */
from_physical_layer(&r); /* uzmi pristigli okvir */
if (r.seq == frame_expected) {
to_network_layer(&r.info); /* prosledi podatke mrežnom sloju */
inc(frame_expected); /* sledeći put očekuj drugi drugi redni broj */
}
s.ack = 1 - frame_expected; /* zabeleži koji je okvir potvrdjen */
to_physical_layer(&s); /* pošalji potvrdu */
}
}
}
Provera rada protokola
konačnim automatom
• Stanja automata označimo sa SRC gde je
S = 0 ili 1, okvir koji pošiljalac pokušava da šalje
R = 0 ili 1, okvir koji primalac očekuje
C = 0, 1, - ili A, i predstavlja stanje kanala
• Imamo 16 mogućih stanja
• Nisu sva stanja dostupna iz inicijalnog
Provera rada protokola
konačnim automatom
• Konačni automat za protokol 3
Provera rada protokola
konačnim automatom
• Na osnovu automata ispitujemo
potencijalne greške u definisanju protokola
 Ne sme postojati putanja u kojoj pošiljalac dva
puta menja stanje, dok primalac ostaje u
istom stanju
 Deadlock – postoji podskup dostupnih stanja
iz kog nema prelaza i unutar koga nije
moguće napredovanje protokola
Protokol kliznih prozora
• Dvosmerni prenos podataka
• Moguće “šlepovanje” potvrde uz podatke
Numerisanje paketa od 0 do 2 − 1
n

• Pošiljalac (primalac) u svakom trenutku čuvaja
skup rednih brojeva okvira koje sme da pošalje
(primi)
• Veličina prozora je ograničena veličinom bafera
• Granice prozora ne moraju biti konstantne
veličine
Protokol 4 - jednobitni protokol kliznih prozora
#define MAX_SEQ 1 while (true) {
typedef enum {frame_arrival, wait_for_event(&event);
cksum_err, timeout} event_type; if (event == frame_arrival) {
#include "protocol.h“ from_physical_layer(&r);

void protocol4 (void) if (r.seq == frame_expected) {


{ to_network_layer(&r.info);
seq_nr next_frame_to_send; inc(frame_expected);
seq_nr frame_expected; }
frame r, s;
packet buffer; if (r.ack == next_frame_to_send) {
event_type event; from_network_layer(&buffer);
inc(next_frame_to_send);
next_frame_to_send = 0; }
frame_expected = 0; }
from_network_layer(&buffer); s.info = buffer;
s.info = buffer; s.seq = next_frame_to_send;
s.seq = next_frame_to_send; s.ack = 1 - frame_expected;
s.ack = 1 - frame_expected; to_physical_layer(&s);
to_physical_layer(&s); start_timer(s.seq);
start_timer(s.seq); }
}
Protokol 5
tipa “vrati se N”
• Kada primalac dobije pogrešan okvir ili ga
uopšte ne dobije, sve sledeće okvire
odbacuje ne šaljući za njih potvrdu
• Ovoj strategiji odgovara prozoru pirmaoca
veličine 1
• Takodje, izostavljamo pretpostavku da
mrežni sloj uvek ima spreman paket za
slanje
#define MAX_SEQ 7 /* Treba biti 2^n - 1 */
typedef enum {frame_arrival, cksum_err, timeout, network_layer_ready} event_type;
#include "protocol.h"

static boolean between(seq_nr a, seq_nr b, seq_nr c)


{
/* Vrati true ako ciklično važi (a <=b < c) */
if (((a <= b) && (b < c)) || ((c < a) && (a <= b)) || ((b < c) && (c < a)))
return(true);
else
return(false);
}

static void send_data(seq_nr frame_nr, seq_nr frame_expected, packet buffer[])


{
/* Napravi i pošalji okvir podataka */
frame s;

s.info = buffer[frame_nr]; /* Unesi paket u okvir */


s.seq = frame_nr; /* unesi redni broj u okvir */
s.ack = (frame_expected + MAX_SEQ) % (MAX_SEQ + 1); /* šlepuj potvrdu */
to_physical_layer(&s); /* pošalji okvir */
start_timer(frame_nr); /* uključi tajmer */
}
void protocol5(void)
{
seq_nr next_frame_to_send; /* MAX_SEQ > 1; koristi se za odlazni tok */
seq_nr ack_expected; /* poslednji potvrdjeni okvir */
seq_nr frame_expected; /* sledeći okvir koji se očekuje u dolaznom toku */
frame r;
packet buffer[MAX_SEQ+1]; /* baferi za odlazni tok */
seq_nr nbuffered; /* broj izlaznih bafera koji se trenutno koriste */
seq_nr i; /* za indeksiranje niza bafera */
event_type event;

enable_network_layer(); /* omogućava dogadjaje network_layer_ready */


ack_expected = 0; /* sledeća očekivana dolazna potvrda */
next_frame_to_send = 0; /* sledeći okvir koji se šalje*/
frame_expected = 0; /* broj očekivanog dolaznog okvira */
nbuffered = 0; /* na početku nema paketa u baferu */

while (true) {
wait_for_event(&event); /* četiri mogućnosti */
switch(event) {
case network_layer_ready: /* mrežni sloj ima paket za slanje */
/* Prihvatanje, memorisanje i slanje novog okvira */
from_network_layer(&buffer[next_frame_to_send]); /* uzmi nov paket */
nbuffered = nbuffered + 1; /* proširi prozor pošiljaoca */
send_data(next_frame_to_send, frame_expected, buffer); /* pošalji okvir */
inc(next_frame_to_send); /* pomeri gornju granicu prozora pošiljaoca */
break;

case frame_arrival: /* stigao okvir s korisničkim ili upravljačkim podacima */


from_physical_layer(&r); /* uzmi pristigli okvir iz fizičkog sloja */

if (r.seq == frame_expected) { /* Okviri se prihvataju samo ispravnim redosledom */


to_network_layer(&r.info); /* prosledi paket mrežnom sloju */
inc(frame_expected); /* pomeri donju granicu prozora primaoca */
}

/* Potvrda n podrazumeva n - 1, n - 2, itd. */


while (between(ack_expected, r.ack, next_frame_to_send)) {
/* Obradi šlepovanu potvrdu. */
nbuffered = nbuffered - 1; /* u baferu je jedan okvir manje */
stop_timer(ack_expected); /* okvir je stigao ispravan, zaustavi tajmer */
inc(ack_expected); /* suzi prozor pošiljaoca */
}
break;
case cksum_err: break; /* zanemari neispravne okvire*/

case timeout: /* pošalji ponovo sve okvire za koje nije stigla potvrda */
next_frame_to_send = ack_expected; /* počni sa ponovnim slanjem odavde */
for (i = 1; i <= nbuffered; i++) {
send_data(next_frame_to_send, frame_expected, buffer);
inc(next_frame_to_send); /* pripremi se da pošalješ sledeći okvir */
}
}

if (nbuffered < MAX_SEQ)


enable_network_layer();
else
disable_network_layer();
}
}
Slanje okvira i oporavljanje od
grešaka kod protokola 5
Selektivno ponavljanje
• Problem kod protokola 5 je trošenje velikog dela
propusnog opsega kada su greške česte.
• Ovde primalac baferuje pristigle podatke koji se
nalaze unutar predviđenog prozora.
• Pošiljalac pokreće tajmer za svaki paket i pri
isteku tajmera šalje samo odgovarajući paket.
• Dozvoljava mogućnost da paketi putuju različitim
putanjama (ne stižu poslatim redosledom), a da
ih sloj veze isporučuje mrežnom sloju
ispravanim redosledom.
#define MAX_SEQ 7 /* treba biti 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; /* nije poslata nijedna negativna potvrda */
seq_nr oldest_frame = MAX_SEQ+1; /* inicijalna vrednost */

static void send_frame(frame_kind fk, seq_nr frame_nr, seq_nr frame_expected, packet


buffer[])
{
/* Kreira i šalje okvir sa podacima, pozitivnom ili negativnom potvrdom. */
frame s;
s.kind = fk; /* kind == data, ack, or nak */
if (fk == data) s.info = buffer[frame_nr % NR_BUFS];
s.seq = frame_nr; /* Ima smisla samo za okvire sa podacima*/
s.ack = (frame_expected + MAX_SEQ) % (MAX_SEQ + 1);
if (fk == nak) no_nak = false;
to_physical_layer(&s); /* pošalji okvir */
if (fk == data) start_timer(frame_nr % NR_BUFS);
stop_ack_timer(); /* moguće je šlepovanje potvrde */
}
void protocol6(void)
{
seq_nr ack_expected; /* donja granica prozora pošiljaoca */
seq_nr next_frame_to_send; /* gornja granica prozora pošiljaoca + 1 */
seq_nr frame_expected; /* donja granica prozora primaoca */
seq_nr too_far; /* gornja granica prozora primaoca + 1 */
int i;
frame r;
packet out_buf[NR_BUFS]; /* baferi za podatke koji se šalju */
packet in_buf[NR_BUFS]; /* baferi za podatke koji stižu */
boolean arrived[NR_BUFS]; /* bit mapa pristiglih okvira */
seq_nr nbuffered; /* koliko se odlaznih bafera trenutno koristi */
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);

switch(event) {

case network_layer_ready: /* prihvati, smesti u memoriju i pošalji novi okvir */


nbuffered = nbuffered + 1; /* proširi prozor */
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); /* pomeri gornju granicu prozora */
break;
case frame_arrival: /* stigao je okvir sa podacima ili upravljački okvir */
from_physical_layer(&r); /* uzmi dolazni okvir iz fizičkog sloja */
if (r.kind == data) { /* stigao je neoštećen okvir */
if ((r.seq != frame_expected) && no_nak)
send_frame(nak, 0, frame_expected, out_buf);
else start_ack_timer(); /* čekamo određeno vreme za šlepovanje potvrde */
if (between(frame_expected, r.seq, too_far) && (arrived[r.seq%NR_BUFS] == false)) {
/* Okviri se mogu primati bilo kojim redom */
arrived[r.seq % NR_BUFS] = true; /* označi odgovarajući bafer kao pun */
in_buf[r.seq % NR_BUFS] = r.info; /* unesi podatke u bafer */
while (arrived[frame_expected % NR_BUFS]) {
/* Prosledi okvire i pomeri prozor */
to_network_layer(&in_buf[frame_expected % NR_BUFS]);
no_nak = true;
arrived[frame_expected % NR_BUFS] = false;
inc(frame_expected); /* pomeri donju granicu prozora primaoca */
inc(too_far); /* pomeri gornju granicu prozora primaoca */
start_ack_timer(); /* čekamo da šlepujemo potvrdu za prosleđeni okvir */
}
}
}
if((r.kind==nak) && between(ack_expected,(r.ack+1)%(MAX_SEQ+1),next_frame_to_send))
send_frame(data, (r.ack+1) % (MAX_SEQ + 1), frame_expected, out_buf);

while (between(ack_expected, r.ack, next_frame_to_send)) {


nbuffered = nbuffered - 1;
stop_timer(ack_expected % NR_BUFS);
inc(ack_expected); /* pomeri donju granicu prozora pošiljaoca */
} break;
/* okvir je oštećen, pošalji NAK poruku */
case cksum_err:
if (no_nak) send_frame(nak, 0, frame_expected, out_buf); break;

/* Nismo dobili potvrdu za najstariji okvir, šaljemo ga ponovo */


case timeout: send_frame(data, oldest_frame, frame_expected, out_buf); break;

/* Mrežni sloj već dugo nema pakete za slanje, šaljemo potvrdu bez podataka */
case ack_timeout: send_frame(ack,0,frame_expected, out_buf);
}

if (nbuffered < NR_BUFS) enable_network_layer(); else disable_network_layer();


}
}
Selektivno ponavljanje
Selektivno ponavljanje
sa NAK porukom

You might also like