Provided by: manpages-fr-dev_3.57d1p1-1_all bug

NOM

       getaddrinfo_a,  gai_suspend,  gai_error,  gai_cancel  -  Traduction  asynchrone d'adresses et de services
       réseau

SYNOPSIS

       #define _GNU_SOURCE         /* Consultez feature_test_macros(7) */
       #include <netdb.h>

       int getaddrinfo_a(int mode, struct gaicb *list[],
                       int nitems, struct sigevent *sevp);

       int gai_suspend(struct gaicb *list[], int nitems,
                       struct timespec *timeout);

       int gai_error(struct gaicb *req);

       int gai_cancel(struct gaicb *req);

       Effectuez l'édition des liens avec l'option -lanl.

DESCRIPTION

       La fonction getaddrinfo_a() effectue la  même  opération  que  getaddrinfo(3),  mais  permet  d'effectuer
       plusieurs  résolutions  de  manière  asynchrone  et  de  recevoir  une  notification  à chaque résolution
       effectuée.

       Le champ mode peut prendre une des valeurs suivantes :

       GAI_WAIT
              Effectue les résolutions de manière synchrone. L'appel bloque tant que les résolutions ne sont pas
              terminées.

       GAI_NOWAIT
              Effectue  les  résolutions  de  manière asynchrone. L'appel s'achève immédiatement et les requêtes
              sont résolues en arrière-plan. Consultez la description du paramètre sevp ci-dessous.

       Le tableau list indique les requêtes de recherche à  traiter.  Le  paramètre  nitems  indique  le  nombre
       d'éléments  dans list. Les opérations de recherche demandées sont lancées en parallèle. Les éléments égal
       à NULL de list sont ignorés. Chaque requête est décrite par une structure gaicb définie ci-dessous :

           struct gaicb {
               const char            *ar_name;
               const char            *ar_service;
               const struct addrinfo *ar_request;
               struct addrinfo       *ar_result;
           };

       Les éléments de cette structure correspondent aux paramètres de getaddrinfo(3). Ainsi, ar_name correspond
       au  paramètre  node  et ar_service au paramètre service, identifiant respectivement un hôte et un service
       Internet. L'élément ar_request correspond au paramètre hints,  indiquant  le  critère  de  sélection  des
       structures  d'adresse de socket renvoyées. Enfin, ar_result correspond au paramètre res ; vous n'avez pas
       besoin d'initialiser ce paramètre, il sera automatiquement défini lorsque la  requête  sera  résolue.  La
       structure addrinfo référencée par les deux derniers éléments est décrite dans getaddrinfo(3).

       Lorsque  mode est défini à GAI_NOWAIT, les notifications des requêtes résolues peuvent être obtenues avec
       la structure sigevent pointée par le paramètre sevp. Pour la définition et les détails généraux de  cette
       structure, consultez sigevent(7). Le champ sevp->sigev_notify peut prendre l'une des valeurs suivantes :

       SIGEV_NONE
              Ne fournit pas de notification.

       SIGEV_SIGNAL
              Lorsqu'une  recherche  se  termine,  générer  le  signal  sigev_signo  à destination du processus.
              Consultez sigevent(7) pour plus de détails. Le champ si_code de la structure siginfo_t sera défini
              à SI_ASYNCNL.

       SIGEV_THREAD
              Lors  d'une  résolution,  invoquer  sigev_notify_function comme si c'était la fonction de création
              d'un nouveau processus léger. Consultez sigevent(7) pour plus détails.

       Pour SIGEV_SIGNAL et SIGEV_THREAD, il peut être utile de faire pointer  sevp->sigev_value.sival_ptr  vers
       list.

       La  fonction  gai_suspend()  suspend  l'exécution  du processus léger appelant, attendant la fin d'une ou
       plusieurs requêtes du tableau list. L'argument nitems indique la taille  du  tableau  list.  L'appel  est
       bloquant tant que l'un des événements suivants ne se produisent :

       *  Une ou plusieurs des opérations de list se sont terminées.

       *  L'appel a été interrompu par un signal qui a été interrompu.

       *  L'intervalle de temps indiqué dans timeout s'est écoulé. Ce paramètre indique un délai en seconds plus
          nanosecondes (consultez nanosleep(2) pour plus de détails sur la structure timespec). Si  timeout  est
          NULL, alors l'appel est bloqué indéfiniment (à moins que l'un des événement ci-dessus se produisent).

       Aucune  indication explicite sur la requête qui s'est terminée est fournie ; vous devez déterminer quelle
       requête s'est terminée en parcourant avec gai_error() la liste des requête (il  peut  y  avoir  plusieurs
       requêtes).

       La fonction gai_error() renvoie l'état de la requête req : soit EAI_INPROGRESS si la requête ne s'est pas
       encore terminée, soit 0 si elle s'est terminé correctement ou soit un code d'erreur si elle ne  peut  pas
       être résolue.

       La  fonction  gai_cancel()  annule  la  requête  req.  Si la requête a été annulée avec succès, le statut
       d'erreur de la requête sera défini à EAI_CANCELLED et un notification asynchrone normale  sera  exécutée.
       La  requête  ne  peut  pas être annulée si elle est en cours d'utilisation ; dans ce cas, elle continuera
       comme si gai_cancel() n'avait jamais été appelée. Si req est NULL, une tentative d'annulation  de  toutes
       les requêtes en cours que le processus a fait sera exécutée.

VALEUR RENVOYÉE

       La fonction getaddrinfo_a() renvoie 0 si toutes les requêtes ont été mises en file d'attente avec succès,
       ou un des codes d'erreur non nuls suivants :

       EAI_AGAIN
              Les ressources nécessaires pour mettre en file d'attente les requêtes de  recherche  ne  sont  pas
              disponibles.  L'application  devrait vérifier le statut d'erreur de chaque requête pour déterminer
              laquelle a échoué.

       EAI_MEMORY
              Plus de mémoire disponible.

       EAI_SYSTEM
              mode est non valable.

       La fonction gai_suspend() renvoie 0 si au moins une des requêtes  listées  s'est  terminée.  Sinon,  elle
       renvoie un des codes d'erreur non nuls suivants :

       EAI_AGAIN
              Le délai d'attente a expiré avant que toute requête ne soit terminée.

       EAI_ALLDONE
              Il n'y a actuellement aucune requête fournie à la fonction.

       EAI_INTR
              Un  signal a interrompu la fonction. Notez que cette interruption pourrait avoir été causé par une
              notification de signal de fin de certaines requêtes de recherche.

       La fonction gai_error() peut renvoyer EAI_INPROGRESS pour une requête de recherche non terminée,  0  pour
       une  recherche  terminée  avec succès (cas décrit ci-dessus), un des codes d'erreur qui peut être renvoyé
       par getaddrinfo(3), ou le code d'erreur EAI_CANCELLED si la requête a  été  annulée  explicitement  avant
       quelle ne soit terminée.

       La fonction gai_cancel() peut renvoyer une des valeurs suivantes :

       EAI_CANCELLED
              La requête a été annulée avec succès.

       EAI_NOTCANCELLED
              La requête n'a pas été annulée.

       EAI_ALLDONE
              La requête est déjà terminée.

       La  fonction  gai_strerror(3)  traduit  ces  codes  d'erreur  en une chaîne de caractères compréhensible,
       utilisable pour rendre compte du problème.

CONFORMITÉ

       Ces fonctions sont des extensions GNU. Elles ont été introduites dans la glibc dans sa version 2.1.1.

NOTES

       L'interface de getaddrinfo_a() a été modifiée après l'interface lio_listio(3).

EXEMPLE

       Deux exemples sont fournis : un simple exemple  qui  résout  plusieurs  requête  en  parallèle  de  façon
       synchrone et un exemple complexe montrant certaines des capacités asynchrones.

   Exemple synchrone
       Le  programme  ci-dessous  résout  simplement  plusieurs noms d'hôte en parallèle, améliorant le temps de
       résolution des noms d'hôtes comparé à des appels séquentiels à getaddrinfo(3).  Le  programme  peut  être
       utilisé comme suit :

           $ ./a.out ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz
           ftp.us.kernel.org: 128.30.2.36
           enoent.linuxfoundation.org: Name or service not known
           gnu.cz: 87.236.197.13

       Voilà le code source du programme

       #define _GNU_SOURCE
       #include <netdb.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <string.h>

       int
       main(int argc, char *argv[])
       {
           int i, ret;
           struct gaicb *reqs[argc - 1];
           char host[NI_MAXHOST];
           struct addrinfo *res;

           if (argc < 2) {
               fprintf(stderr, "Usage: %s HOST...\n", argv[0]);
               exit(EXIT_FAILURE);
           }

           for (i = 0; i < argc - 1; i++) {
               reqs[i] = malloc(sizeof(*reqs[0]));
               if (reqs[i] == NULL) {
                   perror("malloc");
                   exit(EXIT_FAILURE);
               }
               memset(reqs[i], 0, sizeof(*reqs[0]));
               reqs[i]->ar_name = argv[i + 1];
           }

           ret = getaddrinfo_a(GAI_WAIT, reqs, argc - 1, NULL);
           if (ret != 0) {
               fprintf(stderr, "getaddrinfo_a() failed: %s\n",
                       gai_strerror(ret));
               exit(EXIT_FAILURE);
           }

           for (i = 0; i < argc - 1; i++) {
               printf("%s: ", reqs[i]->ar_name);
               ret = gai_error(reqs[i]);
               if (ret == 0) {
                   res = reqs[i]->ar_result;

                   ret = getnameinfo(res->ai_addr, res->ai_addrlen,
                           host, sizeof(host),
                           NULL, 0, NI_NUMERICHOST);
                   if (ret != 0) {
                       fprintf(stderr, "getnameinfo() failed: %s\n",
                               gai_strerror(ret));
                       exit(EXIT_FAILURE);
                   }
                   puts(host);

               } else {
                   puts(gai_strerror(ret));
               }
           }
           exit(EXIT_SUCCESS);
       }

   Exemple asynchrone
       Cet  exemple  est  une  simple  application interactive utilisant getaddrinfo_a(). Les fonctionnalités de
       notification ne sont pas exploitées.

       Un exemple de session pourrait ressembler à ceci :

           $ ./a.out
           > a ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz
           > c 2
           [2] gnu.cz: Request not canceled
           > w 0 1
           [00] ftp.us.kernel.org: Finished
           > l
           [00] ftp.us.kernel.org: 216.165.129.139
           [01] enoent.linuxfoundation.org: Processing request in progress
           [02] gnu.cz: 87.236.197.13
           > l
           [00] ftp.us.kernel.org: 216.165.129.139
           [01] enoent.linuxfoundation.org: Name or service not known
           [02] gnu.cz: 87.236.197.13

       Le code source du programme est :

       #define _GNU_SOURCE
       #include <netdb.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <string.h>

       static struct gaicb **reqs = NULL;
       static int nreqs = 0;

       static char *
       getcmd(void)
       {
           static char buf[256];

           fputs("> ", stdout); fflush(stdout);
           if (fgets(buf, sizeof(buf), stdin) == NULL)
               return NULL;

           if (buf[strlen(buf) - 1] == '\n')
               buf[strlen(buf) - 1] = 0;

           return buf;
       }

       /* Add requests for specified hostnames */
       static void
       add_requests(void)
       {
           int nreqs_base = nreqs;
           char *host;
           int ret;

           while ((host = strtok(NULL, " "))) {
               nreqs++;
               reqs = realloc(reqs, nreqs * sizeof(reqs[0]));

               reqs[nreqs - 1] = calloc(1, sizeof(*reqs[0]));
               reqs[nreqs - 1]->ar_name = strdup(host);
           }

           /* Queue nreqs_base..nreqs requests. */

           ret = getaddrinfo_a(GAI_NOWAIT, &reqs[nreqs_base],
                               nreqs - nreqs_base, NULL);
           if (ret) {
               fprintf(stderr, "getaddrinfo_a() failed: %s\n",
                       gai_strerror(ret));
               exit(EXIT_FAILURE);
           }
       }

       /* Wait until at least one of specified requests completes */
       static void
       wait_requests(void)
       {
           char *id;
           int i, ret, n;
           struct gaicb const **wait_reqs = calloc(nreqs, sizeof(*wait_reqs));
                       /* NULL elements are ignored by gai_suspend(). */

           while ((id = strtok(NULL, " ")) != NULL) {
               n = atoi(id);

               if (n >= nreqs) {
                   printf("Bad request number: %s\n", id);
                   return;
               }

               wait_reqs[n] = reqs[n];
           }

           ret = gai_suspend(wait_reqs, nreqs, NULL);
           if (ret) {
               printf("gai_suspend(): %s\n", gai_strerror(ret));
               return;
           }

           for (i = 0; i < nreqs; i++) {
               if (wait_reqs[i] == NULL)
                   continue;

               ret = gai_error(reqs[i]);
               if (ret == EAI_INPROGRESS)
                   continue;

               printf("[%02d] %s: %s\n", i, reqs[i]->ar_name,
                      ret == 0 ? "Finished" : gai_strerror(ret));
           }
       }

       /* Cancel specified requests */
       static void
       cancel_requests(void)
       {
           char *id;
           int ret, n;

           while ((id = strtok(NULL, " ")) != NULL) {
               n = atoi(id);

               if (n >= nreqs) {
                   printf("Bad request number: %s\n", id);
                   return;
               }

               ret = gai_cancel(reqs[n]);
               printf("[%s] %s: %s\n", id, reqs[atoi(id)]->ar_name,
                      gai_strerror(ret));
           }
       }

       /* List all requests */
       static void
       list_requests(void)
       {
           int i, ret;
           char host[NI_MAXHOST];
           struct addrinfo *res;

           for (i = 0; i < nreqs; i++) {
               printf("[%02d] %s: ", i, reqs[i]->ar_name);
               ret = gai_error(reqs[i]);

               if (!ret) {
                   res = reqs[i]->ar_result;

                   ret = getnameinfo(res->ai_addr, res->ai_addrlen,
                                     host, sizeof(host),
                                     NULL, 0, NI_NUMERICHOST);
                   if (ret) {
                       fprintf(stderr, "getnameinfo() failed: %s\n",
                               gai_strerror(ret));
                       exit(EXIT_FAILURE);
                   }
                   puts(host);
               } else {
                   puts(gai_strerror(ret));
               }
           }
       }

       int
       main(int argc, char *argv[])
       {
           char *cmdline;
           char *cmd;

           while ((cmdline = getcmd()) != NULL) {
               cmd = strtok(cmdline, " ");

               if (cmd == NULL) {
                   list_requests();
               } else {
                   switch (cmd[0]) {
                   case 'a':
                       add_requests();
                       break;
                   case 'w':
                       wait_requests();
                       break;
                   case 'c':
                       cancel_requests();
                       break;
                   case 'l':
                       list_requests();
                       break;
                   default:
                       fprintf(stderr, "Bad command: %c\n", cmd[0]);
                       break;
                   }
               }
           }
           exit(EXIT_SUCCESS);
       }

VOIR AUSSI

       getaddrinfo(3), inet(3), lio_listio(3), hostname(7), ip(7), sigevent(7)

COLOPHON

       Cette page fait partie de la publication 3.57 du projet man-pages Linux. Une description du projet et des
       instructions     pour     signaler     des     anomalies    peuvent    être    trouvées    à    l'adresse
       http://www.kernel.org/doc/man-pages/.

TRADUCTION

       Depuis 2010, cette traduction est maintenue à l'aide de l'outil po4a <http://po4a.alioth.debian.org/> par
       l'équipe de traduction francophone au sein du projet perkamon <http://perkamon.alioth.debian.org/>.

       Veuillez  signaler  toute erreur de traduction en écrivant à <debian-l10n-french@lists.debian.org> ou par
       un rapport de bogue sur le paquet manpages-fr.

       Vous pouvez toujours avoir accès à la version anglaise de ce document en utilisant la commande « man -L C
       <section> <page_de_man> ».