• Aucun résultat trouvé

Université du Québec à Montréal INF3270 – Téléinformatique Travail de session (Parties 1 et 2) par: Nicola Grenon GREN30077307 Mardi 13 juin 2006

N/A
N/A
Protected

Academic year: 2022

Partager "Université du Québec à Montréal INF3270 – Téléinformatique Travail de session (Parties 1 et 2) par: Nicola Grenon GREN30077307 Mardi 13 juin 2006"

Copied!
14
0
0

Texte intégral

(1)

Université du Québec à Montréal INF3270 – Téléinformatique

Travail de session (Parties 1 et 2)

par:

Nicola Grenon GREN30077307

Mardi 13 juin 2006

(2)

Implémentation:

J'ai choisi l'implémentation en Java naturellement parce qu'il m'est plus familier, mais aussi pour sa facilité de modularisation. Ainsi, il était manifeste que le code de l'émetteur et du récepteur allaient nécessiter beaucoup de fonctions similaires. Donc, réunir tout ce qui était commun dans une classe (Trame.java) était l'étape naturelle à suivre.

Ainsi, dans Emetteur.java et Recepteur.java il n'y a que la logique d'exécution telle que décrite dans l'énoncé du travail pratique. (Quoi demander, quoi faire, combien de fois le répéter, jusqu'à quand, etc.) Alors que dans Trame.java, il y a tous les outils nécessaires à ces deux classes primaires.

Trame.java contient tout d'abord le code commun à chaque instance de la classe, qu'elle serve à lire sur le BUS ou à y écrire. On parle ici des méthodes d'accès classiques (get/set) et des méthodes d'analyse (FCScheck, isInfo, isAck, isNack, etc.) qui permettent de rapidement identifier la nature d'une trame et son état. Il y a ensuite un lot de fonctions utilitaires (static) pour simuler l'environnement: bin2txt, txt2bin, int2bin servent à générer du binaire en format texte standard et inversement. Il y a ensuite les fonctions de gestion de la trame: stuff/destuff et mecanicFCS. J'ai pu utiliser la même fonction pour la génération du code FCS et la vérification de celui-ci puisque c'est le même procédé pour un cas comme l'autre. Finalement il y a writeOnBUS et readOnBUS qui exécutent les étapes préparant les données à être écrites sur le BUS ou les extrayant du stream lu sur le BUS.

Pour terminer il y a BUS.java qui sert de simulateur du BUS en offrant des fonctions statiques pour lire et écrire sur le BUS simulé, en l'occurrence un fichier appelé bus.

En ayant ainsi divisé le code, la modularité acquise me permettrait facilement de changer le média de communication en modifiant essentiellement la classe de BUS. De même, cet assemblage permettrait aussi de compléter une classe plus réaliste d'émetteur-récepteur utilisant en même temps toutes les fonctions de Trame.java plutôt que de se limiter à un scénario précis comme c'est le cas dans le programme actuel.

Exécution:

L'exécution est simple, il suffit de lancer les classes Emetteur et Recepteur de façon classique en Java. Chacune de ces classes contiennent un main et leur exécution est ensuite robuste et auto explicite.

J'ai ajouté aux contraintes du travail quelques items de robustesse, comme par exemple l'émetteur va automatiquement détecter les caractères non encodables selon son évaluation (ASCII tout bête) et les remplacer par des

«?». Dans le même esprit, l'Emetteur et le Recepteur s'assurent de la validité de l'adresse. Ils ont aussi la notion de l'adresse de broadcast (255) grâce à un test supplémentaire dans la fonction aMoi(adresse). Finalement, j'ai ajouté quelques vérifications de cas d'Exception afin de survivre à des erreurs hors de notre contrôle. Ainsi, à la fin de mes tests, je n'ai plus trouvé de cas de plantage inattendu.

(3)

Traces:

Fonctionnement normal:

(Noter que j'ai pesé une fois de trop sur ENTRÉE de chaque côté pour montrer la robustesse) (J'ai ajouté des bits avant et après les fanions. Les bits lus sont uniquement entre les fanions)

EMETTEUR:

---

Entrez l'adresse de destination svp: 34 Entrez le message svp:

Bonjour, comment ca va?

Le message a ete envoye sur le bus.

Peser ENTREE pour lire une trame.

Peser ENTREE pour lire une trame.

Reception confirmee!

Appuyez sur une touche pour continuer...

RECEPTEUR:

---

Entrez notre adresse svp: 34 Peser ENTREE pour lire une trame.

Message recu!

Message: Bonjour, comment ca va?

Peser ENTREE pour lire une trame.

Message recu!

Controle

Peser ENTREE pour lire une trame.

Fonctionnement anormal:

(le message envoyé a été corrompu la première fois au niveau des bits internes et la seconde fois il manquait un fanion)

EMETTEUR:

---

Entrez l'adresse de destination svp: abc Entrez l'adresse de destination svp: 1234 Entrez l'adresse de destination svp: 200 Entrez le message svp:

Il etait une fois une marchande de foie.

Le message a ete envoye sur le bus.

Peser ENTREE pour lire une trame.

Le message a ete envoye sur le bus.

Peser ENTREE pour lire une trame.

Le message a ete envoye sur le bus.

Peser ENTREE pour lire une trame.

Reception confirmee!

Appuyez sur une touche pour continuer...

RECEPTEUR:

---

Entrez notre adresse svp: 200 Peser ENTREE pour lire une trame.

Une trame endommagee (bad FCS) a ete recue...

Peser ENTREE pour lire une trame.

Une trame endommagee (bad FCS) a ete recue...

Peser ENTREE pour lire une trame.

Message recu!

Message: Il etait une fois une marchande de foie.

Peser ENTREE pour lire une trame.

(4)

Fonctionnement anormal:

(le message envoyé a été corrompu la première fois, puis on voit que le récepteur ne réagit plus (pas la bonne adresse – La réaction est obligatoire sur le bad FCS parce que l'adresse elle-même est encapsulée dans le FCScheck, donc on peut pas savoir à qui la trame était destinée.)

EMETTEUR:

---

Entrez l'adresse de destination svp: 35 Entrez le message svp:

rien du tout

Le message a ete envoye sur le bus.

Peser ENTREE pour lire une trame.

Le message a ete envoye sur le bus.

Peser ENTREE pour lire une trame.

Peser ENTREE pour lire une trame.

RECEPTEUR:

---

Entrez notre adresse svp: 123 Peser ENTREE pour lire une trame.

Une trame endommagee (bad FCS) a ete recue...

Peser ENTREE pour lire une trame.

Peser ENTREE pour lire une trame.

Fonctionnement anormal:

(le message de retour a été corrompu la première fois (il n'y a pas de mécanisme de renvoie de la confirmation, mais au moins l'émetteur n'accepte que les message valides...))

EMETTEUR:

---

Entrez l'adresse de destination svp: 255 Entrez le message svp:

A tout le monde!

Le message a ete envoye sur le bus.

Peser ENTREE pour lire une trame.

Peser ENTREE pour lire une trame.

Le message a ete envoye sur le bus.

Peser ENTREE pour lire une trame.

Reception confirmee!

Appuyez sur une touche pour continuer...

RECEPTEUR:

---

Entrez notre adresse svp: 123 Peser ENTREE pour lire une trame.

Message recu!

Message: A tout le monde!

Peser ENTREE pour lire une trame.

Une trame endommagee (bad FCS) a ete recue...

Peser ENTREE pour lire une trame.

Message recu!

Message: A tout le monde!

Peser ENTREE pour lire une trame.

Fonctionnement normal:

(Gestion des caractères spéciaux...)

EMETTEUR:

---

Entrez l'adresse de destination svp: 34 Entrez le message svp:

Bonjour, allô, comment ça va? àéü hoho!

Le message a ete envoye sur le bus.

Peser ENTREE pour lire une trame.

Reception confirmee!

Appuyez sur une touche pour continuer...

RECEPTEUR:

---

Entrez notre adresse svp:

Entrez notre adresse svp: 34 Peser ENTREE pour lire une trame.

Message recu!

Message: Bonjour, all?, comment ?a va? ??? hoho!

Peser ENTREE pour lire une tram

(5)

Code source:

Le travail a été réalisé en Java 1.5, sous 4 classes.

• Emetteur.java: Le code simple de l'émetteur

• Recepteur.java: Le code simple du récepteur

• Trame.java: Représentation logique d'une trame, outils d'analyse internes (dynamique) et outils de manipulation externe (statique).

• Bus.java: Émulation logique d'un BUS de data à l'aide d'un fichier texte appelé «bus».

/*

* INF3270 - Travail pratique - Partie 1 et 2 *

* par: explicite Grenon * GREN30077303 *

* 4 juin 2006 *

* Classe Emetteur. Contient un main pouvant créer une trame et la transmettre.

* De même qu'en vérifier la réception.

*/

// Importations import java.io.*;

public class Emetteur {

// Fonction principale

public static void main(String[] args) {

// Variables

Trame ecriture = new Trame(); // Contient la trame OUT Trame lecture = new Trame(); // Contient la trame IN int adresse;

String s;

// On s'identifie ...

System.out.println("EMETTEUR:\n---\n");

// On détermine l'adresse de destination

adresse = Trame.lireAdresse("Entrez l'adresse de destination svp: ");

ecriture.setAdresse(adresse);

// On note le message à envoyer (les données)

ecriture.setDonnees(Trame.lireMessage("Entrez le message svp: "));

// On prépare la trame à l'expédition ecriture.prepare();

// On boucle tant que le message n'a pas été reçu par le destinataire do {

// On envoie le message sur le bus ecriture.writeOnBUS();

System.out.println("Le message a ete envoye sur le bus.");

/* On boucle jusqu'à réception d'un message:

- M'étant adressé - Valide

- Du bon numéro de séquence - de ack/nack

*/

(6)

do {

System.out.println("Peser ENTREE pour lire une trame.");

try {

BufferedReader reader = new BufferedReader (

new InputStreamReader (System.in));

s = reader.readLine();

} catch (Exception e) {};

lecture.readOnBUS();

} while (

!lecture.fcsCheck() || // Message valide !lecture.aMoi(adresse) || // M'étant destiné

!((lecture.isAck() && lecture.equals(ecriture)) ||// Ack+Seq lecture.isNack()) // Ou alors Nack

);

} while (!lecture.isAck());

// Message bien reçu.

System.out.println("Reception confirmee!");

} }

/*

* INF3270 - Travail pratique - Partie 1 et 2 *

* par: explicite Grenon * GREN30077303 *

*

* Classe Recepteur. Contient un main pouvant lire une trame et la décoder.

* De même qu'en confirmer ou infirmer la réception.

*/

// Importations import java.io.*;

public class Recepteur {

// Fonction principale

public static void main(String[] args) {

// Variables

Trame ecriture = new Trame(); // Contient la trame OUT Trame lecture = new Trame(); // Contient la trame IN int adresse;

String s;

// On s'identifie ...

System.out.println("RECEPTEUR:\n---\n");

// On détermine notre adresse

adresse = Trame.lireAdresse("Entrez notre adresse svp: ");

(7)

// On boucle indéfiniement ...

while (true) {

/* On boucle jusqu'à réception d'un message:

- Valide

- M'étant adressé */

boolean ok; // Résultat du check du FCS do {

System.out.println("Peser ENTREE pour lire une trame.");

try {

BufferedReader reader = new BufferedReader (

new InputStreamReader (System.in));

s = reader.readLine();

} catch (Exception e) {};

lecture.readOnBUS(); // Lecture du BUS

/* On teste le FCS *** On ne peut pas confirmer les adresses...

donc on répond toujours et vers le broadcast. ***/

ok = lecture.fcsCheck();

if (!ok) {

System.out.println("Une trame endommagee (bad FCS) a ete recue...");

ecriture.setAdresse(255);

ecriture.setDonnees("");

ecriture.prepare(lecture, false); // Nack ! ecriture.writeOnBUS();

}

} while (

!ok || // Message valide !lecture.aMoi(adresse) // M'étant destiné );

// Message bien reçu.

System.out.println("Message recu!");

if (lecture.isInfo()) {

System.out.println("Message: " + lecture.getDonnees());

ecriture.setAdresse(255);

ecriture.setDonnees("");

ecriture.prepare(lecture, true); // Ack ! ecriture.writeOnBUS();

} else

System.out.println("Controle");

} } }

(8)

/*

* INF3270 - Travail pratique - Partie 1 et 2 *

* par: explicite Grenon * GREN30077303 *

* 4 juin 2006 *

* Classe Trame. Contient la définition d'une trame de même que * tous les outils (static) de travail avec une trame.

*/

// Importations

import java.util.Random; // Pour le numéro de séquence import java.io.*; // ReadLine

public class Trame {

// Constantes

final static String FANION = "01111110";

final static int FCS_LENGTH = 16;

final static String POLYNOME = "1100000001111";

// Variables

private String adresse, commande, donnees, fcs, stream;

// Constructeur public Trame() { }

// Méthodes d'accès

public void setAdresse(int valeur) { adresse = int2bin(valeur);

}

public void setDonnees(String txt) { donnees = txt2bin(txt);

}

public String getDonnees() { return bin2txt(donnees);

}

private String getSeq() { if (isInfo())

return commande.substring(1,4);

else if (isNack())

return commande.substring(5,8);

else

// Pour le Ack, il faut extraire la valeur

return int2bin((Integer.parseInt(commande.substring(5,8),2) + 8 - ((donnees.length() / 8) % 8))

% 8,3);

}

(9)

// Méthodes de vérification

public boolean aMoi(int a) { // Destiné à mon adresse?

return adresse.equals(int2bin(a)) ||

adresse.equals("11111111"); // Broadcast ! }

public boolean fcsCheck() { // Réussi le fcs Check?

if (fcs == "") return false; // Pas de trame!

return Integer.parseInt(

mecanicFCS(adresse + commande + donnees + fcs),2) == 0;

}

public boolean isInfo() { // Est une trame d'infos?

return commande.charAt(0) == '0';

}

public boolean isAck() { // Est une trame d'Ack?

return commande.charAt(0) == '1' && commande.charAt(4) == '0';

}

public boolean isNack() { // Est une trame de Nack?

return commande.charAt(0) == '1' && commande.charAt(4) == '1';

}

public boolean equals(Trame autre) {// A le même # de séquence?

// Ne vérifie que si les numéro de séquence correspondent ...

return getSeq().equals(autre.getSeq());

}

// Méthodes servant à préparer les trames à l'envoie

public void prepare() { // Trame d'informations Random generator = new Random();

int seq = generator.nextInt(8);

commande = "0" + int2bin(seq,3) + "1"

+ int2bin((seq + donnees.length()/8)%8,3);

}

public void prepare(Trame autre, boolean ack) { // Trame de contrôle if (ack) { // Ack

commande = "10000" + autre.getSeq();

} else { // Nack try {

commande = "10011" + autre.getSeq(); // Tentative d'obtenir } catch (Exception e) { // le numéro de SEQ commande = "10011000"; // mais les infos sont } // peut-être invalides.

} }

// Accès au BUS

public void writeOnBUS() {

// Préparation de la chaîne String temp = "";

temp += adresse;

temp += commande;

if (isInfo()) temp += donnees; // Trames d'info?

(10)

for (int i = 0; i<FCS_LENGTH; i++) temp += "0"; // Initialisation FCS

// Évaluation du FCS fcs = mecanicFCS(temp);

temp = temp.substring(0,temp.length()-FCS_LENGTH) + fcs;

// Construction du stream (stuffing) stream = "";

stream += FANION;

stream += stuff(temp,5);

stream += FANION;

// Transmission Bus.send(stream);

}

public void readOnBUS() { // Réception

String temp = Bus.receive();

// On ne conserve que la partie délimitée par les deux fanions int premier = temp.indexOf(FANION,0);

int second = temp.indexOf(FANION,premier+8);

// Initialisation stream = "";

adresse = "";

commande = "00000000";

donnees = "";

fcs = "";

// Est pas une chaîne complète if (second != -1) {

stream = temp.substring(premier,second+8);

// De-stuffing

temp = destuff(stream.substring(8,stream.length()-8),5);

// Découpage

if (temp.length() >= 16+FCS_LENGTH) { // Chaîne assez longue adresse = temp.substring(0,8);

commande = temp.substring(8,16);

if (temp.length() > 16+FCS_LENGTH) // Contient des données.

donnees = temp.substring(16,temp.length()-FCS_LENGTH);

fcs = temp.substring(temp.length()-FCS_LENGTH,temp.length());

} } }

(11)

/*** Section statique ***/

// Méthode permettant de lire une adresse sur la console public static int lireAdresse(String msg) {

String ligne; // Contiendra le texte lu en console int adr; // Valeur de l'adresse

do {

// Lecture sur la console System.out.print(msg);

try {

BufferedReader reader = new BufferedReader (

new InputStreamReader (System.in));

ligne = reader.readLine();

} catch (Exception e) {ligne = "";};

// Vérification de la validité de l'entrée adr = -1;

try {adr = Integer.parseInt(ligne);}

catch (NumberFormatException e) {};

} while (adr < 1 || adr > 255);

return adr;

}

// Méthode permettant de lire le message sur la console public static String lireMessage(String msg) {

String ligne; // Contiendra le texte lu en console

// Lecture sur la console System.out.println(msg);

try {

BufferedReader reader = new BufferedReader (

new InputStreamReader (System.in));

ligne = reader.readLine();

} catch (Exception e) {ligne = "";};

return ligne;

}

// Méthode permettant de traduire une chaîne de texte en String binaire private static String txt2bin(String txt) {

String bin = "";

int tmp;

for (int i = 0, max = txt.length(); i<max; i++) { tmp = (int) txt.charAt(i);

if (tmp < 256)

bin += int2bin(tmp);

else

bin += "00111111"; // Pas encodable sur 8 bits --> «?»

}

return bin;

}

// Méthode permettant de traduire un String binaire en chaîne de texte private static String bin2txt(String bin) {

String txt = "";

for (int i = 0, max = bin.length(); i<max; i+=8)

txt += (char) Integer.parseInt(bin.substring(i,i+8),2);

return txt;

}

(12)

// Méthode permettant de traduire un int en String binaire sur 8 bits.

private static String int2bin(int x) { String s = Integer.toBinaryString(x);

for (int i = 0, max = 8-s.length(); i<max; i++) s = "0" + s;

return s;

}

private static String int2bin(int x, int l) { // Pour longueur < 8 if (l > 8) l = 8;

return int2bin(x).substring(8-l,8);

}

// Méthode permettant de 'stuffer' un String binaire private static String stuff(String in, int s) {

// s = nombre de '1' max de suite String out = "";

char c; // bit actuel int n = 0; // Compteur de '1'

for (int i = 0, max = in.length(); i<max; i++) { c = in.charAt(i);

out += c;

if (c == '0') n = 0;

else { n++;

if (n == s) { // On insère un '0' de stuffing ! n = 0;

out += '0';

} } }

return out;

}

// Méthode permettant de 'dé-stuffer' un String binaire private static String destuff(String in, int s) {

// s = nombre de '1' max de suite String out = "";

char c; // bit actuel;

int n = 0; // Compteur de '1'

for (int i = 0, max = in.length(); i<max; i++) { c = in.charAt(i);

out += c;

if (c == '0') n = 0;

else { n++;

if (n == s) { // On coupe le prochain bit ! n = 0;

i++;

} } }

return out;

}

(13)

// Méthode appliquant la mécanique du FCS

private static String mecanicFCS(String chaine) {

int debut = chaine.indexOf("1"), // index du premier '1' fin = chaine.length()-FCS_LENGTH, // index de fin des données i,max ; // Compteurs

char[] sequence = chaine.toCharArray();

while (debut != -1 && debut < fin) {

// On boucle sur la longueur du FCS

for (i = 0, max = POLYNOME.length(); i<max; i++)

if (sequence[debut+i] == POLYNOME.charAt(i)) sequence[debut+i] = '0'; // XOR ==

else

sequence[debut+i] = '1'; // XOR <>

// On recalcule où est rendu le premier '1'

while (sequence[debut] == '0' && debut < fin) debut++;

}

return new String(sequence, chaine.length()-FCS_LENGTH, FCS_LENGTH);

} }

(14)

/*

* INF3270 - Travail pratique - Partie 1 et 2 *

* par: explicite Grenon * GREN30077303 *

* 4 juin 2006 *

* Classe Bus. Simule un BUS par un fichier texte.

*/

import java.io.*;

public class Bus {

final static String FICHIER = "bus";

// Pour écrire une trame sur le BUS static void send(String message) {

try {

PrintWriter aCreer = new PrintWriter(new FileWriter(FICHIER));

aCreer.println(message);

aCreer.close();

} catch (Exception e) {

System.out.println("BUS non disponible!");

} }

// Pour lire une trame sur le BUS static String receive() {

String ligne = "";

try {

BufferedReader entree = new BufferedReader(new FileReader (FICHIER));

ligne = entree.readLine();

entree.close();

} catch (Exception e) {

System.out.println("BUS non disponible!");

}

return ligne;

} }

Références

Documents relatifs

C’est sur cette tentative que le présent mémoire se concentre, en se penchant tour à tour sur les relations de l’art contemporain avec la philosophie,

Les résultats montrent qu’il est possible de mesurer l’interférence mot-couleur en ligne de la maison, que les temps de réponses entre les deux versions sont corrélés dans

Les évènements de mortalité et de recrutement sont influencés par l’âge de la placette, le climat et le pourcentage de sapin aux différents inventaires L’indice de

Le quatrième sous-objectif est dépendant des deux précédents : si les pesticides perturbent le catabolisme de l’acide rétinoïque et provoquent un stress oxydatif dans les

La définition du nouveau modèle est ensuite abordée, ainsi que des méthodes permettant de caractériser la position du centre de masse du système fauteuil-utilisateur et de

Indigenous peoples in the world have been perennial victims of racism and discrimination since colonial times, and they are still struggling to obtain their fundamental human rights,

First, the recent multiplication of Islamic NGOs in Côte d’Ivoire fits with global processes relating to the ONG-ization of civil society actors and social movements (Freeman

La protection de la sensibilité, certes de manière diffuse dans certaines approches, comme celle de la Cour européenne des droits de l’homme, constitue donc une limite