Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Client IPv4/IPv6 : comment coder proprement ?

8 views
Skip to first unread message

Olivier Miakinen

unread,
Feb 1, 2013, 3:40:46 PM2/1/13
to
[diapublication, suivi vers fr.comp.reseaux.ip]

Bonjour,

Grâce à Jérémie Courrèges-Anglas sur fr.comp.reseaux.ip, j'ai déjà eu
pas mal de réponses très intéressantes concernant la programmation des
sockets en IPv4 et IPv6.

Pour cette nouvelle question, je fais de nouveau une diapublication dans
trois groupes (f.c.reseaux.ip, f.c.os.unix et f.c.lang.c) avec suivi
vers fr.comp.reseaux.ip seul.

***

À l'époque d'IPv4 il était exceptionnel qu'une machine non routeur
ait plus d'une adresse IP non locale, mais avec IPv6 au contraire
c'est la règle d'avoir plusieurs adresses IP.

Comme en plus les adresses sont longues comme un jour sans pain et
immémorisables, il est conseillé de ne retenir que le nom DNS d'une
machine à laquelle on veut se connecter par TCP, et d'appliquer le
petit algorithme suivant :
- faire un getaddrinfo(hostname, port) pour obtenir toutes les
adresses correspondantes ;
- faire une boucle sur chaque adresse pour tenter de faire le
socket() puis le connect() jusqu'à ce que la connexion réussisse.
Cf. à la fin de cet article une fonction do_connect() écrite en C
et implémentant cet algorithme (j'espère ne pas avoir laissé traîné
d'erreur).

***

Tout cela est bel et bon s'agissant d'une socket connectée (SOCK_STREAM,
typiquement TCP). Mais ce que je voudrais savoir, c'est comment diable
on peut bien faire dans le cas d'une socket en SOCK_DGRAM (UDP) ! Non
seulement il n'y a pas de connect() pour nous dire si l'adresse distante
est la bonne, mais même le premier sendto() pourrait très bien ne pas
retourner d'erreur alors que l'hôte distant ne recevra jamais le paquet.

Et donc comment faire ? J'ai essayé de trouver des réponses sur le web,
mais je ne vois que des exemples en SOCK_STREAM.

***

P.-S. : le code pour socket connectée :
===========================================================================
int do_connect(const char *hostname, const char *port)
{
struct addrinfo hints;
struct addrinfo *result, *aip;
int cc;
int sock;

memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;

cc = getaddrinfo(hostname, port, &hints, &result);
if (cc != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(cc));
return -1;
}

for (aip = result; aip != NULL; aip = aip->ai_next) {
sock = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
if (sock < 0)
continue;

if (connect(sock, aip->ai_addr, aip->ai_addrlen) == 0)
break; /* success */

close(sock);
}

freeaddrinfo(result);

if (aip == NULL) { /* No address succeeded */
fprintf(stderr, "Could not connect\n");
return -1;
}

return sock;
}
===========================================================================


Cordialement,
--
Olivier Miakinen
0 new messages