Aller au contenu principal

VI. Description informelle des opérations réseau

Nous présentons ici des récits décrivant les opérations menées au cours des trois grandes phases d'utilisation du réseau : l'ouverture, le contrôle de flux et la fermeture.

A. Ouverture​

Pour établir une connexion destinée à la transmission de données, une paire de RFC doit être échangée. Un RTS doit aller du côté réception vers le côté émission, et un STR doit être émis par le côté émission vers le côté réception. En outre, le côté réception doit, dans son RTS, spécifier un numéro de lien. Ces RFC (RFC est un terme générique englobant RTS et STR) peuvent être émis dans n'importe quel ordre temporel. Il faut également prévoir la mise en file des appels en attente (c.-à-d. des RFC qui n'ont pas encore été traités par le programme utilisateur). Ainsi, lorsqu'un utilisateur en a terminé avec une connexion, il peut choisir d'examiner l'appel en attente suivant, provenant d'un autre processus, et décider d'accepter ou de refuser la demande de connexion. Un problème se pose parce que l'utilisateur peut choisir de ne pas examiner ses appels en attente ; ceux-ci ne serviront alors qu'à occuper de l'espace de file dans le NCP. Plusieurs solutions possibles à ce problème seront mentionnées plus loin.

En nous appuyant sur le cadre des appels système prototypes décrits ci-dessus, nous envisageons au moins quatre séquences temporelles permettant d'obtenir une connexion ouverte avec succès :

  1. L'utilisateur peut émettre un LISTEN, indiquant qu'il est disposé à envisager une connexion avec quiconque lui envoie un RFC. Lorsqu'un RFC arrive, l'utilisateur en est averti. L'utilisateur décide alors s'il souhaite se connecter à ce socket et émet un ACCEPT ou un CLOSE en fonction de cette décision. Un CLOSE « refuse » la connexion, comme expliqué sous « Fermeture ». Un ACCEPT indique qu'il est disposé à se connecter ; un RFC est émis et la connexion devient entièrement ouverte.
  2. En traitant une requête LISTEN d'un utilisateur, le NCP découvre qu'un appel en attente existe pour ce socket local. L'utilisateur en est immédiatement averti et il peut répondre par ACCEPT ou CLOSE, comme ci-dessus.
  3. L'utilisateur émet un CONNECT, en spécifiant un socket distant particulier auquel il souhaite se connecter. Un RFC est émis. Si le processus distant accepte la requête, il répond en renvoyant un RFC. Lorsque ce RFC d'acquittement est reçu, la connexion est ouverte.
  4. Lorsqu'on lui présente un CONNECT, le NCP peut découvrir qu'un appel en attente existe depuis le socket distant spécifié vers le socket local en question. Un RFC d'acquittement est émis et la connexion est ouverte.

Dans tous les cas ci-dessus, l'utilisateur est averti lorsque la connexion est ouverte, mais le flux de données ne peut commencer qu'une fois l'espace tampon alloué et une commande ALL transmise.

N'importe lequel de ces scénarios de connexion sera interrompu si un CLS arrive, comme expliqué sous « Fermeture ».

1. Files des appels en attente​

Il est essentiel d'implémenter une forme de mise en file des RFC en attente. Une manière simple de s'en rendre compte est d'examiner une séquence LISTEN-CONNECT typique. Un côté émet un LISTEN, l'autre un CONNECT. Si le LISTEN est émis avant l'arrivée du RFC provenant du CONNECT distant, tout va bien. Cependant, en raison de la nature asynchrone du réseau, nous ne pouvons jamais garantir que les événements se produiront dans cet ordre. Si les appels ne sont pas mis en file et que le RFC arrive avant l'émission du LISTEN, il sera refusé ; s'il arrive plus tard, il sera accepté. Nous nous trouvons donc dans une situation extrêmement ambiguë.

À moins de disposer d'un espace de file infini, il est souhaitable de prévoir un mécanisme pour purger les files des anciens RFC que l'utilisateur n'a jamais pris la peine d'examiner. Une méthode évidente mais informelle consiste à noter l'heure à laquelle chaque RFC est placé dans la file, puis à refuser périodiquement tous les RFC qui ont dépassé une limite de temps arbitraire. Une autre idée, qui devrait probablement être incluse dans le cadre de tout schéma, est que le NCP envoie un CLS sur toutes les connexions en cours ou tous les appels en attente lorsqu'un utilisateur se déconnecte ou plante.

Le schéma utilisé dans cette description peut sembler à première vue peu intuitif ; mais nous estimons qu'il est plus réaliste que d'autres propositions. En substance, lorsqu'un CONNECT est émis, le NCP suppose que ce socket souhaite dialoguer avec le socket distant spécifié et avec ce socket uniquement. Il purge donc de la file des appels en attente tous les RFC non correspondants en renvoyant des CLS. De même, lorsque la connexion est dans l'état RFC-SENT (un CONNECT a été émis), tous les RFC non correspondants sont refusés. Si une séquence LISTEN-ACCEPT ou LISTEN-CLOSE est exécutée, le reste des appels en attente n'est pas retiré de la file, dans l'éventualité où l'utilisateur souhaiterait accepter ces requêtes à l'avenir.

Bien que cette dernière méthode puisse sembler arbitraire et/ou inutilement restrictive, nous n'avons pas encore imaginé de scénario qu'elle interdirait, à condition d'avoir affaire à un programmeur compétent (c.-à-d. attentif aux conditions de concurrence et à la nature asynchrone du réseau). Bien entendu, le ou les schémas qu'un site particulier choisit dépendent fortement de l'implémentation ; nous suggérons de prévoir une mise en file des RFC pendant une durée au moins du même ordre de grandeur que celle pendant laquelle ils sont conservés dans le schéma de purge par CONNECT mentionné ci-dessus.

B. Contrôle de flux​

Des données significatives ne peuvent circuler sur une connexion que lorsque celle-ci est entièrement ouverte (c.-à-d. que deux RFC ont été échangés et que la fermeture n'a pas commencé). Nous supposons que les NCP disposent d'un tampon pour recevoir les données entrantes et qu'il existe une quantité significative qu'ils peuvent annoncer (connexion par connexion) indiquant la taille de message qu'ils peuvent traiter. Nous supposons en outre que le côté émission régule sa transmission en fonction des annonces de cette taille.

Lorsqu'une connexion est ouverte, une cellule (appelée 'Their Size') est mise à zéro. Le côté réception décide de la quantité d'espace qu'il peut allouer et envoie un message ALL spécifiant cet espace. Le côté émission incrémente 'Their Size' de l'espace alloué et peut alors envoyer des messages de longueur inférieure ou égale à 'Their Size'. Lorsque des messages sont transmis, la longueur du message est soustraite de 'Their Size'. Lorsque le côté réception alloue davantage d'espace tampon (par ex. lorsqu'un message est pris par l'utilisateur, libérant ainsi de l'espace tampon système), le nombre de bits libérés est envoyé au côté émission au moyen d'un message ALL.

Ainsi, 'Their Size' ne peut jamais devenir négatif et aucune transmission ne peut avoir lieu si 'Their Size' est égal à zéro.

Notez que les longueurs spécifiées dans les messages ALL sont des incréments et non la taille absolue du tampon de réception. Cela est rendu nécessaire par la nature full duplex du protocole de contrôle de flux. Le champ de longueur du message ALL peut avoir une longueur de 32 bits (remarque : il s'agit d'un entier non signé), ce qui offre la possibilité d'un « puits de bits » pratiquement infini, si cela devait un jour être souhaité.

C. Fermeture​

De même que deux RFC sont nécessaires pour ouvrir une connexion, deux CLS sont nécessaires pour la fermer. La fermeture se produit dans diverses circonstances et sert plusieurs objectifs. Pour simplifier l'analyse des conditions de concurrence, nous distinguons quatre cas : l'abandon, le refus, la terminaison par le récepteur et la terminaison par l'émetteur.

Un utilisateur abandonne ("aborts") une connexion lorsqu'il émet un CONNECT puis un CLOSE avant que le CONNECT n'ait été acquitté. Typiquement, un utilisateur abandonne après une longue attente de l'acquittement ; son système peut aussi abandonner à sa place s'il plante.

Un utilisateur refuse ("refuses") une connexion lorsqu'il émet un LISTEN puis, après avoir été averti d'un appelant potentiel, émet un CLOSE. Toute demande de connexion à un socket qui attend un appel d'un socket particulier est également refusée.

Une fois la connexion établie, l'un ou l'autre côté peut y mettre fin. La séquence d'événements requise suggère que les tentatives de CLOSE par le côté réception soient considérées comme des demandes ("requests") toujours honorées dès que possible par le côté émission. Toute donnée qui n'a pas encore été transmise à l'utilisateur, ou qui est encore en transit sur le réseau, est rejetée. Les demandes de CLOSE par le côté émission sont honorées dès que toute la transmission de données est terminée.

1. Abandon​

Nous pouvons distinguer trois cas :

  • a) Dans le cas le plus simple, nous envoyons un RFC suivi plus tard d'un CLS. L'autre côté répond par un CLS et la tentative de connexion prend fin.
  • b) Le processus distant peut accepter la connexion au moment même où le processus local l'abandonne. Dans ce cas, le processus distant croira que le processus local met fin à une connexion ouverte.
  • c) Le processus distant peut refuser la connexion au moment même où le processus local l'abandonne. Dans ce cas, le processus distant croira que le processus local acquitte son refus.

2. Refus​

Après la réception d'un RFC, l'hôte local peut répondre par un RFC ou un CLS, ou ne pas répondre du tout. (L'hôte local peut avoir déjà envoyé son propre RFC, etc.) Si l'hôte local envoie un CLS, on dit que l'hôte local refuse ("refusing") la demande de connexion.

Nous exigeons que des commandes CLS soient échangées pour fermer une connexion ; il est donc nécessaire que l'hôte local conserve l'entrée de la table de rendez-vous jusqu'au retour d'un CLS d'acquittement.

3. Terminaison par l'émetteur​

Lorsque l'utilisateur du côté émission émet un appel système CLOSE, son NCP doit l'accepter immédiatement, mais ne peut envoyer une commande CLS que lorsque toutes les données des tampons locaux ont été transmises à l'hôte distant. Il est donc nécessaire de tester à la fois 'buffer-empty' et 'RFNM-received' avant d'envoyer la commande CLS. Comme d'habitude, le CLS doit être acquitté avant que l'entrée puisse être supprimée.

4. Terminaison par le récepteur​

Lorsque l'utilisateur du côté réception émet un appel système CLOSE, son NCP l'accepte et envoie immédiatement la commande CLS. Des données peuvent toutefois encore arriver, et ces données doivent être rejetées. Le côté émission, à la réception du CLS, doit immédiatement interrompre le flux de données.