4. Choisir entre socket simple ou double

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.

dual stack single socket

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.

dual stack double socket

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

bindv6only = 0

vm1.fake.domain

Serveur ou listener

socket double

bindv6only = 1 -> socket IPv6

vm1.fake.domain

Client dual stack

disable_ipv6 = 0

vm2.fake.domain

IPv6

IPv6

Client single stack

disable_ipv6 = 1

vm3.fake.domain

IPv6

IPv4-mapped IPv6 addresses

IPv4