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 :
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 T
Est_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;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.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
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 puisse limiter le débit d'émission de . On a principalement 2 techniques, soit 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 est potentiellement toujours saturable et alors n'émettra une nouvelle trame qu'après autorisation venant de . 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 :
Il est d'autre part nécessaire de supposer que chaque machine et 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 (resp. entre R2 ou R3 et E'1 sur ).
Les procédures Emission et Reception deviennent alors :
proc'edure Ēmission2;où 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 . La fonction Traiter_info lors de la réception d'un Ack consistera à mettre Non_reçu_Ack à false.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 T
Est_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
Pour la partie réception, on peut écrire :
proc'edure Reception2;où la procédure Emettre consiste à demander à la procédure E'1 d'émission en d'envoyer une trame de type Ack.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
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. aura envoyé 2 fois les même données qui sont reçu correctement par , mais ne doit les délivrer qu'une fois à son utilisateur. Il faut donc que 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 puisse décider quand il y a duplication sur les trames reçues.
La structure de la trame est maintenant :
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;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.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 T
Est_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
proc'edure Reception3;où valide(sequence_bit) vérifie la validité de la redondance et Extraire capture les différents champs de la trame.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
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é.