next up previous
Next: Àpropos de ce Up: Solution Petite Classe Concept Previous: Multiplexage

Gestion d'une liaison de données

Etape 1

Les fonctions à mettre en oeuvre sont la synchronisation et le remplissage inter-trame, la délimitation, la transparence (nécessaire à cause de la délimitation) .

La structure la plus simple va consister à délimiter l'information utile par 2 séquences particulières appelées FLAG ou Fanion. On peut prendre la même séquence pour délimiter la fin et le début d'une trame. On pourra alors n'utiliser qu'un fanion qui pourra être à la fois la fin de la trame précédente et le début de la trame suivante. D'autre part, pour le cas où le niveau physique désire une occupation permanente du support, on fera du bourrage par émission continue de fanions.

Par exemple on aura la transmission suivante :

....FLAG.Info1.FLAG.FLAG.FLAG.Info2.FLAG.Info3.FLAG...

La procédure d'émission peut alors s'écrire :

 proc'edure  Ēmission1;

variables :

s, Flag: Sequence_de_bits

Liaison_ok:Bool'een

d'ebut

Flag:=''01111110''

Liaison_ok:=true

Envoyer(Flag)

tant que Liaison_ok faire

si TEst_Vide(User-Buffer)

alors Envoyer(Flag)

sinon s:=Contenu(User-Buffer)

Envoyer( Insere-Zero(s))

Envoyer(Flag)

Purge(User-Buffer)

fin_si

fin_tant_que;

fin

Pour la partie réception, on peut écrire :

 proc'edure  Reception1;

variables :

s: Sequence_de_bits

Liaison_ok:Bool'een

d'ebut

Liaison_ok:=true

tant que Liaison_ok faire

s:=Supprime_Zero(Lecture_jusqu'a_flag)

si non_vide(s) alors Traiter_info(s) fin_si

fin_tant_que;

fin

où non_vide(sequence) teste si la séquence est vide, et Traiter_info(sequence) signifie délivrer l'information à l'utilisateur de la procédure.

Contrôle de flux

Il peut y avoir saturation au niveau du récepteur, ce qui dans le cas précédent correspond à un temps pour la fonction Traiter_info trop long par rapport à la lecture des trames.

Il faut donc que B puisse limiter le débit d'émission de A. On a principalement 2 techniques, soit B est par défaut prêt à recevoir et il enverra une trame de contrôle particulière en cas de saturation (RNR en HDLC), soit B est potentiellement toujours saturable et alors A n'émettra une nouvelle trame qu'après autorisation venant de B. C'est cette deuxième technique que l'on va étudier. Chaque trame envoyée donne lieu à un acquittement et une trame ne peut être envoyée qu'après réception de l'acquittement de la trame précédente. L'acquittement indique la bonne réception et le traitement d'une trame.

Il faut donc maintenant avoir plusieurs types de trame. La trame peut prendre la forme :

FLAG.Type.Info.FLAG
Type prend les valeurs Data ou Ack et peut être codé sur 1 bit, le champ Info n'est présent que dans les trames Data.

Il est d'autre part nécessaire de supposer que chaque machine A et B dispose de procédures E'1 et R'1 permettant de gérer la réception et l'émission des acquittements. On ne réécrira pas ces procédures qui sont similaires aux procédures de la première étape. On restera aussi vague sur la façon de communiquer entre les procédures d'émission E2 ou E3 et R'1 sur la machine A (resp. entre R2 ou R3 et E'1 sur B).

Les procédures Emission et Reception deviennent alors :

 proc'edure  Ēmission2;

variables :

s, Flag, Ack, Data: Sequence_de_bits

Non_reçu_Ack,Liaison_ok:Bool'een

d'ebut

Flag:=''01111110''

Data:=''0''

Ack:=''1''

Liaison_ok:=true

Envoyer(Flag)

tant que Liaison_ok faire

si TEst_Vide(User-Buffer)

alors Envoyer(Flag)

sinon s:=Data + Contenu(User-Buffer)

Non_Reçu_Ack:=true

Envoyer( Insere-Zero(s))

Envoyer(Flag)

tant que Non_reçu_Ack faire Envoyer(Flag) fin_tant_que

Purge(User-Buffer)

fin_si

fin_tant_que

fin

+ correspond à la concaténation de séquences et la variable Non_reçu_Ack est mise à jour par la procédure R'1 de réception des acquittements en A. La fonction Traiter_info lors de la réception d'un Ack consistera à mettre Non_reçu_Ack à false.

Pour la partie réception, on peut écrire :

 proc'edure  Reception2;

variables :

s,Ack, Data: Sequence_de_bits

Liaison_ok:Bool'een

d'ebut

Data:=''0''

Ack:=''1''

Liaison_ok:=true

tant que Liaison_ok faire

s:=Supprime_Zero(Lecture_jusqu'a_flag)

si non_vide(s)

alors Traiter_info(s)

Emettre(Ack)

fin_si

fin_tant_que;

fin

où la procédure Emettre consiste à demander à la procédure E'1 d'émission en B d'envoyer une trame de type Ack.

Et les erreurs alors !

Il faut maintenant gérer la détection d'erreur et la reprise sur erreur.

La détection d'erreur va être réalisée en rajoutant une information redondant sur chaque trame transmise avec un algorithme que l'on ne précisera pas ici (A et B doivent utiliser le même). Pour la reprise, l'émetteur devra réémettre une trame si celle ci n'est pas acquittée au bout d'un temps donné. D'autre part, on comptera le nombre de reprises consécutives afin de déclarer la liaison hors service après Reprise-Max reprises. Pour le récepteur, il n'acquittera pas les trames non reçus ou mal reçus.

A partir du moment où l'on retransmet des trames, il y a risque de duplication d'une trame de données. Cela va arriver en particulier lors de la perte d'une trame d'acquittement. A aura envoyé 2 fois les même données qui sont reçu correctement par B, mais B ne doit les délivrer qu'une fois à son utilisateur. Il faut donc que B sache identifier si il reçoit une nouvelle trame ou la réémission de la trame reçue précédemment. Le seul moyen simple (un pot a gagner pour une autre solution simple) est de numéroter les trames de données émises afin que B puisse décider quand il y a duplication sur les trames reçues.

La structure de la trame est maintenant :

FLAG.Type.Numero.Info.redondance.FLAG
Les champs Type et redondance sont obligatoires, les champs Numero et Info ne sont que dans les trames de données.

On considérera de plus, un temporisateur T sur lequel on a les fonctions : Armer(T) qui démarre T et Non_expire(T) qui indique si la Temporisation est expirée ou non.

Les procédures Emission et Reception deviennent alors :

 proc'edure  Ēmission3;

variables :

s, Flag, Ack, Data: Sequence_de_bits

Non_reçu_Ack,Liaison_ok:Bool'een

Num:Compteur_Modulo_X (X=2 suffisant)

Nombre_Reprise:entier

d'ebut

Flag:=''01111110''

Data:=''0''

Ack:=''1''

Num:=0

Nombre_reprise:=0

Liaison_ok:=true

Envoyer(Flag)

tant que Liaison_ok faire

si TEst_Vide(User-Buffer)

alors Envoyer(Flag)

sinon s:=Data + codage(num)+Contenu(User-Buffer)

s:=s+ redondance(s)

Non_Reçu_Ack:=true

Envoyer( Insere-Zero(s))

Envoyer(Flag)

Armer(T)

tant que Non_reçu_Ack et Non_expire(T) faire

Envoyer(Flag)

fin_tant_que

si Non_reçu_Ack

alors Nombre_Reprise:= Nombre_Reprise+1 (et je recommence)

sinon(je continu)

Purge(User-Buffer)

Num:=(Num +1) modulo X

Nombre_Reprise:=0

fin_si

fin_si

Liaison_ok:= (Nombre_Reprise < Reprise_Max)

fin_tant_que

fin

où codage(entier) fait un codage binaire d'une valeur entière, redondance(sequence_bit) calcule l'information redondante pour la validité de la trame.

 proc'edure  Reception3;

variables :

s,s.info,s.type,s.num,s.redondance,Ack, Data: Sequence_de_bits

Liaison_ok:Bool'een

Num:Compteur_Modulo_X (X=2 suffisant)

d'ebut

Data:=''0''

Ack:=''1''

Num:=0

Liaison_ok:=true

tant que Liaison_ok faire

s:=Supprime_Zero(Lecture_jusqu'a_flag)

si non_vide(s) et valide(s)

alors Ēmettre(Ack+redondance(Ack))

Extraire(s,s.info,s.num)

sinum=s.num

alors Traiter_info(s.info)

Num:=(Num +1) modulo X

sinon (ne rien faire, duplication)

fin_si

fin_si

fin_tant_que;

fin

où valide(sequence_bit) vérifie la validité de la redondance et Extraire capture les différents champs de la trame.

Le rédacteur vous félicite d'être arrivé ici, et vous prie de l'excuser pour les imprécisions, les lourdeurs, ou même les erreurs qui subsisteraient dans cette seconde version de corrigé.


next up previous
Next: Àpropos de ce Up: Solution Petite Classe Concept Previous: Multiplexage

Pascal Hennequin (LOR-AIGRI)
Tue Jan 21 15:56:50 MET 1997