Character stuffing în practică
Cum în software ne este mult mai ușor să lucrăm la nivel de byte decât bit,
nivelul fizic ne oferă și un serviciu de trimitere de fluxuri de bytes. În mod
similar cu bit stuffing, vom folosi mai multe caractere speciale pentru a ne
delimita frame-ul. Vom folosi DLE
, STX
și ETX
definiți în tabela
ASCII
A B C => DLE STX A B C DLE ETX
A B C DLE STX D => DLE STX A B C DLE DLE STX D DLE ETX
Mai jos avem o diagramă care surprinde transmisia de date folosind framing. Vedem cum la nivelul DataLink folosind protocolul nostru simplu cu bytes de separare putem oferi un serviciu de trimitere de frames.
Următorul exemplu prezintă o posibilă implementare de character stuffing
folosind DLE
,STX
și ETX
. Presupunem că am cumpărat o placă de
rețea (NIC) care are în firmware două funcții send_byte
și
recv_byte
. În general, implementarea unui protocol se face într-o bibliotecă
pe care atât programul ce rulează la transmițător cât și cel de la receptor
o folosesc.
Transmiterea este relativ simplă.
/* Transmitem date aflate în buffer */
/* Trimite delimitator */
send_byte(DLE);
send_byte(STX);
/* Trimite bytes din frame */
for (int i = 0; i < size; i++) {
/* Facem escape la escape */
if (buffer[i] == DLE)
send_byte(DLE);
send_byte(buffer[i]);
}
/* Trimite delimitator final */
send_byte(DLE);
send_byte(ETX);
Recepția cadrului are o complexitate mai mare, deoarce în exemplul nostru
recv_byte
întoarce date aleatoare când transmițătorul nu trimite nimic.
char c1, c2;
c1 = recv_byte();
c2 = recv_byte();
/* Cât timp nu am primit DLE STX citim bytes. Atenție la modul în care salvăm
* byte-ul precedent. */
while( ((c1 != DLE) && (c2 != STX)) || (c1 == DLE && c2 != STX) \
|| (c1 != DLE && c2 == STX)) {
c1 = c2;
c2 = recv_byte();
}
/* Am primit începutul unui frame: DLE STX */
for (int i = 0; i < max_size; i++) {
char byte = recv_byte();
/* Dacă am primit un escape */
if (byte == DLE) {
byte = recv_byte();
/* Am primit DLE ETX */
if (byte == ETX)
return i;
/* După DLE, trebuie să primim alt DLE,
altfel frame-ul nu este bine structurat */
else if (byte != DLE)
return -1;
}
/* Punem în buffer conținutul frame-ului */
buffer[i] = byte;
}