Avant d'aborder le codage des applications supportant les deux protocoles de couche réseau, il convient de poser les termes du débat. Deux lignes de conduite s'affrontent depuis des années sans que l'une ait réussi à prendre l'ascendant sur l'autre. L'objectif du présent document n'est pas d'affirmer une position mais d'exposer les arguments des uns et des autres. Ensuite, on étudiera dans les sections suivantes le même programme écrit suivant les deux modes de fonctionnement possibles.
Codage basé sur un socket simple
On pourrait qualifier cette ligne de conduite comme étant la plus académique. En effet, en reprenant les principes énoncés dans le cours sur la modélisation (voir Modélisations réseau), on postule que les traitements réalisés au niveau de chaque couche doivent être indépendants les uns des autres. Dans notre contexte, un programme de la couche application ne doit pas dépendre des protocoles de la couche réseau. Le principal argument en faveur de cette position est la pérennité du modèle. Si les traitements entre couches introduisent des relations de dépendance multiples, nous allons très vite être confronté à un écheveau inextricable. Plus il y aura de dépendances, moins le modèle sera évolutif et pérenne dans le temps.
On peut représenter cette solution comme suit.
Pour satisfaire le critère sur l'unicité du canal de
communication entre la couche réseau et la couche transport, il est
nécessaire d'établir une correspondance automatique entre les
adresses IPv4 et les adresses
IPv6. On parle de IPv4-mapped IPv6 addresses. Par exemple,
l'adresse IPv4 192.0.2.10
devient ::ffff:192.0.2.10
après correspondance.
Codage basé sur deux sockets non bloquants
La seconde ligne de conduite s'appuie sur le fait que le support
de l'option bindv6only
n'est pas
uniforme entre les différents systèmes d'exploitation. On observe
des comportements différents entre les distributions BSD, Linux et les
systèmes propriétaires. Cette option, que l'on applique à l'échelle
du système ou dans une application, sert à définir si une prise
réseau (socket) doit exclusivement être
associée au seul protocole réseau IPv6 ou non.
Les partisans de cette position souhaitent que tous les programmes de la couche application gèrent deux sockets distincts. Cette solution a un impact important sur le codage des applications en langage C dans les domaines voisins de l'espace mémoire noyau comme les systèmes embarqués. Pour les langages «bien encrés» dans l'espace utilisateur, le recours à des bibliothèques de haut niveau permet de rendre l'opération transparente.
On peut représenter cette solution comme suit.
Pour qu'un unique processus puisse exploiter deux canaux de
communication entre les couches application et transport, il est
nécessaire d'utiliser des appels système non bloquants et de
scruter les deux canaux en attente d'évènements. On a alors recours
à la fonction select()
qui permet de
mettre en place une boucle de scrutation (polling).
Programmes et infrastructure de test
Voici un tableau de synthèse des tests effectués avec les différents codes proposés dans ce document.
Tableau 2. Protocole de couche réseau utilisé suivant les conditions de tests
client ou talker |
Serveur ou listener socket unique
|
Serveur ou listener socket double
|
---|---|---|
Client dual stack
|
IPv6 |
IPv6 |
Client single stack
|
IPv6 IPv4-mapped IPv6 addresses |
IPv4 |