Man page - getaddrinfo_a(3)

Packages contains this manual

Available languages:

en fr ja ru

Manual

getaddrinfo_a

NOM
BIBLIOTHÈQUE
SYNOPSIS
DESCRIPTION
VALEUR RENVOYÉE
ATTRIBUTS
STANDARDS
HISTORIQUE
EXEMPLES
Exemple synchrone
Exemple asynchrone
VOIR AUSSI
TRADUCTION

NOM

getaddrinfo_a, gai_suspend, gai_error, gai_cancel – Traduction asynchrone d’adresses et de services rĂ©seau

BIBLIOTHÈQUE

BibliothÚque de résolution de noms asynchrone ( libanl , -lanl )

SYNOPSIS

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

int getaddrinfo_a(int mode , struct gaicb * list [restrict],
int
nitems , struct sigevent *restrict sevp );
int gai_suspend(const struct gaicb *const
list [], int nitems ,
const struct timespec *
timeout );

int gai_error(struct gaicb * req );
int gai_cancel(struct gaicb *
req );

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 (3type). 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 (3type) 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 (3type) 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_CANCELED 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 assez de mémoire.

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_CANCELED 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_CANCELED

La requĂȘte a Ă©tĂ© annulĂ©e avec succĂšs.

EAI_NOTCANCELED

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.

ATTRIBUTS

Pour une explication des termes utilisés dans cette section, consulter attributes (7).

Image grohtml-3889979-1.png

STANDARDS

GNU.

HISTORIQUE

glibc 2.2.3.

L’interface de getaddrinfo_a () a Ă©tĂ© modifiĂ©e aprĂšs l’interface lio_listio (3).

EXEMPLES

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 mirrors.kernel.org enoent.linuxfoundation.org gnu.org
mirrors.kernel.org: 139.178.88.99
enoent.linuxfoundation.org: Name or service not known
gnu.org: 209.51.188.116

VoilĂ  le code source du programme

#define _GNU_SOURCE
#include <err.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MALLOC(n, type) ((type *) reallocarray(NULL, n, sizeof(type)))
int
main(int argc, char *argv[])
{
int ret;
struct gaicb *reqs[argc - 1];
char host[NI_MAXHOST];
struct addrinfo *res;
if (argc < 2) {
fprintf(stderr, "Utilisation : %s HOST...\n", argv[0]);
exit(EXIT_FAILURE);
}
for (size_t i = 0; i < argc - 1; i++) {
reqs[i] = MALLOC(1, struct gaicb);
if (reqs[i] == NULL)
err(EXIT_FAILURE, "malloc");
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() a échoué : %s\n",
gai_strerror(ret));
exit(EXIT_FAILURE);
}
for (size_t 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() a échoué : %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 mirrors.kernel.org enoent.linuxfoundation.org gnu.org
> c 2
[2] gnu.org: Request not canceled
> w 0 1
[00] mirrors.kernel.org: Finished
> l
[00] mirrors.kernel.org: 139.178.88.99
[01] enoent.linuxfoundation.org: Processing request in progress
[02] gnu.org: 209.51.188.116
> l
[00] mirrors.kernel.org: 139.178.88.99
[01] enoent.linuxfoundation.org: Name or service not known
[02] gnu.org: 209.51.188.116

Le code source du programme est :

#define _GNU_SOURCE
#include <assert.h>
#include <err.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CALLOC(n, type) ((type *) calloc(n, sizeof(type)))
#define REALLOCF(ptr, n, type) \
({ \
static_assert(__builtin_types_compatible_p(typeof(ptr), type *)); \
\
(type *) reallocarrayf(ptr, n, sizeof(type)); \
})
static struct gaicb **reqs = NULL;
static size_t nreqs = 0;
static inline void *
reallocarrayf(void *p, size_t nmemb, size_t size)
{
void *q;
q = reallocarray(p, nmemb, size);
if (q == NULL && nmemb != 0 && size != 0)
free(p);
return q;
}
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;
}
/* Ajout des requĂȘtes pour les noms d’hĂŽte spĂ©cifiĂ©s. */
static void
add_requests(void)
{
size_t nreqs_base = nreqs;
char *host;
int ret;
while ((host = strtok(NULL, " "))) {
nreqs++;
reqs = REALLOCF(reqs, nreqs, struct gaicb *);
if (reqs == NULL)
err(EXIT_FAILURE, "reallocf");
reqs[nreqs - 1] = CALLOC(1, struct gaicb);
if (reqs[nreqs - 1] == NULL)
err(EXIT_FAILURE, "calloc");
reqs[nreqs - 1]->ar_name = strdup(host);
}
/* Mettre en file d’attente les requĂȘtes nreqs_base..nreqs. */
ret = getaddrinfo_a(GAI_NOWAIT, &reqs[nreqs_base],
nreqs - nreqs_base, NULL);
if (ret) {
fprintf(stderr, "getaddrinfo_a() a échoué : %s\n",
gai_strerror(ret));
exit(EXIT_FAILURE);
}
}
/* Attendre qu’au moins une des requĂȘtes spĂ©cifiĂ©es soit achevĂ©e. */
static void
wait_requests(void)
{
char *id;
int ret;
size_t n;
struct gaicb const **wait_reqs;
wait_reqs = CALLOC(nreqs, const struct gaicb *);
if (wait_reqs == NULL)
err(EXIT_FAILURE, "calloc");
/* Les éléments NULL sont ignorés par gai_suspend(). */
while ((id = strtok(NULL, " ")) != NULL) {
n = atoi(id);
if (n >= nreqs) {
printf("Mauvais nombre de requĂȘtes : %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 (size_t i = 0; i < nreqs; i++) {
if (wait_reqs[i] == NULL)
continue;
ret = gai_error(reqs[i]);
if (ret == EAI_INPROGRESS)
continue;
printf("[%02zu] %s: %s\n", i, reqs[i]->ar_name,
ret == 0 ? "Terminé" : gai_strerror(ret));
}
}
/* Annuler les requĂȘtes spĂ©cifiĂ©es. */
static void
cancel_requests(void)
{
char *id;
int ret;
size_t n;
while ((id = strtok(NULL, " ")) != NULL) {
n = atoi(id);
if (n >= nreqs) {
printf("Mauvais nombre de requĂȘtes : %s\n", id);
return;
}
ret = gai_cancel(reqs[n]);
printf("[%s] %s: %s\n", id, reqs[atoi(id)]->ar_name,
gai_strerror(ret));
}
}
/* Lister toutes les requĂȘtes. */
static void
list_requests(void)
{
int ret;
char host[NI_MAXHOST];
struct addrinfo *res;
for (size_t i = 0; i < nreqs; i++) {
printf("[%02zu] %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() a échoué : %s\n",
gai_strerror(ret));
exit(EXIT_FAILURE);
}
puts(host);
} else {
puts(gai_strerror(ret));
}
}
}
int
main(void)
{
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, "Mauvaise commande : %c\n", cmd[0]);
break;
}
}
}
exit(EXIT_SUCCESS);
}

VOIR AUSSI

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

TRADUCTION

La traduction française de cette page de manuel a été créée par Christophe Blaess <https://www.blaess.fr/christophe/>, Stéphan Rafin <stephan.rafin@laposte.net>, Thierry Vignaud <tvignaud@mandriva.com>, François Micaux, Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard <fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas Huriaux <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centraliens.net>, Florentin Duneau <fduneau@gmail.com>, Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis Barbier <barbier@debian.org>, David Prévot <david@tilapin.org> et Jean-Pierre Giraud <jean-pierregiraud@neuf.fr>

Cette traduction est une documentation libre ; veuillez vous reporter à la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n’y a aucune RESPONSABILITÉ LÉGALE.

Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message à debian-l10n-french@lists.debian.org .