Uploaded by duma_david2001

Lucrarea 5 - SDC

advertisement
Lucrarea 5. Codificarea datelor în mesaje
1. Scopul lucrării
Lucrarea își propune studiul modului în care se face codificarea datelor de tip întreg,
șir de caractere și variabile booleene în mesajele transmise la distanță la nivelul
protocoalelor de aplicație.
2. Noțiuni teoretice
Două programe care comunică la distanță în cadrul sistemului distribuit trebuie să se
înțeleagă asupra modului de codificare a informației transmise prin canalul de
comunicație. Acest acord privind forma și semnificația datelor schimbate reprezintă un
protocol, care în cazul unei anumite aplicații concrete poartă numele de protocol de
aplicație. Protocoalele de aplicație sunt definite sub formă de mesaje discrete formate
dintr-o secvență de câmpuri, fiecare conținând informație codificată pe șiruri de biți.
Protocolul specifică modul în care informația este codificată și aranjată în mesaj de
către partea emițătoare, respectiv interpretată de partea receptoare. Există protocoale
de aplicație predefinite, standardizate, dar se pot și defini liber de proiectanți în cazuri
izolate.
Prin socluri se pot transmite octeți de date, ca atare vom considera că mesajele sunt
formate din șiruri de octeți. Java necesită ca toate tipurile de date (întregi, șiruri de
caractere) să fie în prealabil convertite în secvențe de octeți.
Codificarea întregilor
În cazul primitivelor de tip întreg partea emițătoare și receptoare trebuie să convină în
prealabil asupra următoarelor lucruri:
− numărul de octeți al fiecărui tip de întreg (fig. 1)
− ordinea de transmitere a octeților (fig. 2)
− dacă numărul este cu semn sau fără semn (primitivele întregi în Java sunt
numere cu semn în complement față de 2)
Codificarea șirurilor de caractere
Cea mai simplă metodă de codificare a caracterelor utilizate în texte constă în utilizarea
unui set de caractere standard asupra căruia cad de acord cele două părți implicate în
transfer. Asemenea seturi de caractere sunt de exemplu ASCII, Unicode UTF-8
compatibil cu ASCII, UTF-16 etc. Când șirurile de caractere într-o anumită ordine
indiană sunt încărcate într-o gazdă cu o altă ordine indiană, atunci șirul trebuie
convertit înainte de a face prelucrarea în regulă. Metoda getBytes() a clasei
String întoarce o secvență de octeți conținând șirul de caractere codificat
corespunzător setului implicit de pe platformă.
Fig. 1. Numărul de octeți al primitivelor de tip întreg
Fig. 2. Ordinea de transmitere a octeților numărului int 12345678
(în hexazecimal 00BC614E)
Codificarea variabilelor booleene
Variabilele booleene se tratează ca și biți individuali ai unei primitive întregi. Fiecare
bit al unei date de tip întreg poate reprezenta câte o valoare booleană (0 pentru fals, 1
pentru adevărat). Setarea unui anumit bit se face prin efectuarea unei operații SAU cu
o mască care conține 1 pe poziția respectivă și 0 în rest. Ștergerea se face cu operația
ȘI efectuată asupra măștii negate.
3. Aplicația propusă
Aplicația își propune codificarea într-un mesaj a câte unei valori corespunzătoare celor
patru tipuri de primitive de tip întreg, urmată de decodificarea și afișarea mesajului
rezultat obținut. Ordinea octeților este de tip big-endian. Se implementează o metodă
encodeIntBigEndian() care poate codifica orice valoare aparținând unui anumit
tip de primitivă întreagă, respectiv o metodă decodeIntBigEndian() pentru
decodificarea unei submulțimi a secvenței de octeți într-o variabilă de tip long.
Pașii programului sunt:
1. Se definesc valorile de codificat, câte una pentru fiecare tip de primitivă
întreagă, și se calculează numărul de octeți al fiecărei variabile.
2. Se definește o metodă pentru transformarea fiecărui octet al unui tablou întrun string în vederea afișării:
public static String byteArrayToDecimalString(byte[] bArray)
3. Se definește metoda encodeIntBigEndian().
4. Se definește metoda decodeIntBigEndian().
5. Se pregătește tabloul care va găzdui mesajul (secvența de întregi).
6. Se codifică datele.
7. Se tipărește conținutul mesajului codificat.
8. Se decodifică și se tipăresc câmpurile tabloului.
9. Se demonstrează diferența dintre interpretarea unui octet ca întreg cu semn,
respectiv întreg fără semn.
Legat de problema interpretării diferite a unui număr întreg cu semn față de unul fără
semn, este de menționat faptul că dacă dorim să decodificăn N octeți ca o valoare fără
semn, atunci rezultatul decodificării trebuie plasat într-un tip de primitivă întreagă care
utilizează cel puțin N+1 octeți [1].
4. Partea practică
1. Scrieți, compilați și rulați pe calculatorul gazdă local programul specificat la
punctul 3. Interpretați rezultatul.
2. Procedura precedentă reprezintă o codificare ”manuală” a datelor într-un
mesaj, dar Java dispune și de mecanisme mai ușor de folosit. Rescrieți
aplicația folosind pentru compunerea mesajului clasele DataOutputStream
și ByteArrayOutputStream. Prima pune la dispoziție metodele
writeByte(), writeShort(), writeInt(), writeLong() care
inserează într-un flux o valoare întreagă reprezentată în complement de 2 pe
numărul de octeți corespunzător în ordinea big-endian. A doua dispune de
metoda toByteArray() care convertește o secvență de octeți din flux întrun tablou de octeți.
BIBLIOGRAFIE
1. K. L. Calvert, M. J. Donahoo, TCP/IP Sockets in Java, Morgan Kaufmann, 2008.
2. G. Coulouris, J. Dollimore, T. Kindberg, Distributed Systems: Concepts and Design, AddisonWesley, 2011.
3. Tutorial Java: www.learn-java-tutorial.com.
Download