Scroll to navigation

getaddrinfo_a(3) Library Functions Manual getaddrinfo_a(3)

الاسم

getaddrinfo_a, gai_suspend, gai_error, gai_cancel - ترجمة غير متزامنة لعنوان الشبكة والخدمة

المكتبة

مكتبة البحث عن الأسماء غير المتزامنة (libanl-lanl)

موجز

#define _GNU_SOURCE         /* انظر feature_test_macros(7) */
#include <netdb.h>
int getaddrinfo_a(int mode, struct gaicb *list[restrict n],
                  int n, struct sigevent *restrict sevp);
int gai_suspend(const struct gaicb *const list[n], int n,
                  const struct timespec *timeout);
int gai_error(struct gaicb *req);
int gai_cancel(struct gaicb *req);

الوصف

الدالة getaddrinfo_a() تؤدي نفس مهمة getaddrinfo(3)، لكنها تسمح بإجراء عمليات بحث متعددة عن الأسماء بشكل غير متزامن، مع إشعار اختياري عند اكتمال عمليات البحث.

المعامل mode له إحدى القيم التالية:

إجراء عمليات البحث بشكل متزامن. يُحجَز الاستدعاء حتى تكتمل عمليات البحث.
إجراء عمليات البحث بشكل غير متزامن. يعود الاستدعاء فورًا، وتُحل الطلبات في الخلفية. انظر مناقشة المعامل sevp أدناه.

المصفوفة list تحدد طلبات البحث التي ستُعالج. المعامل n يحدد عدد العناصر في list. تُبدأ عمليات البحث المطلوبة بالتوازي. تُتجاهل العناصر NULL في list. يُوصف كل طلب بهيكل gaicb، المُعرَّف كالتالي:


struct gaicb {

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

عناصر هذا الهيكل تتوافق مع معاملات getaddrinfo(3). لذا، ar_name يتوافق مع المعامل node و ar_service مع المعامل service، مُعرِّفًا مضيف إنترنت وخدمة. العنصر ar_request يتوافق مع المعامل hints، مُحددًا معايير اختيار هياكل عنوان المقبس المُعادة. أخيرًا، ar_result يتوافق مع المعامل res؛ لا تحتاج لتهيئة هذا العنصر، سيُضبط آليًا عند حل الطلب. هيكل addrinfo المُشار إليه بالعنصرين الأخيرين موصوف في getaddrinfo(3).

عندما يُحدد mode كـ GAI_NOWAIT، يمكن الحصول على إشعارات حول الطلبات المُحلّة باستخدام هيكل sigevent المُشار إليه بالمعامل sevp. للتعريف والتفاصيل العامة لهذا الهيكل، انظر sigevent(3type). الحقل sevp->sigev_notify يمكن أن يكون له القيم التالية:

لا تُقدم أي إشعار.
عند اكتمال بحث، يُولَّد الإشارة sigev_signo للعملية. انظر sigevent(3type) للتفاصيل العامة. الحقل si_code من هيكل siginfo_t سيُضبط إلى SI_ASYNCNL.
عند اكتمال بحث، تُستدعى sigev_notify_function كما لو كانت دالة بدء خيط جديد. انظر sigevent(3type) للتفاصيل.

بالنسبة لـ SIGEV_SIGNAL و SIGEV_THREAD، قد يكون من المفيد توجيه sevp->sigev_value.sival_ptr إلى list.

الدالة gai_suspend() تُعلق تنفيذ الخيط المُستدعي، منتظرة اكتمال طلب واحد أو أكثر في المصفوفة list. المعامل n يحدد حجم المصفوفة list. يُحجَز الاستدعاء حتى يحدث أحد التالي:

تكتمل عملية أو أكثر من العمليات في list.
تُقاطع الاستدعاء بإشارة تم التقاطها.
ينقضي الفاصل الزمني المحدد في timeout. تحدد هذه الوسيطة مهلة بالثواني بالإضافة إلى النانوثانية (انظر nanosleep(2) لتفاصيل بنية timespec). إذا كان timeout NULL، فتحجب الاستدعاء إلى أجل غير مسمى (حتى يقع أحد الأحداث أعلاه).

لا يُعطى إشارة صريحة عن أي طلب أُكمل؛ يجب عليك تحديد أي الطلبات أُكملت بالتكرار مع gai_error() على قائمة الطلبات.

ترجع الدالة gai_error() حالة الطلب req: إما EAI_INPROGRESS إذا لم يُكمل الطلب بعد، أو 0 إذا عُولج بنجاح، أو رمز خطأ إذا تعذر حل الطلب.

تلغي الدالة gai_cancel() الطلب req. إذا أُلغي الطلب بنجاح، فتُضبط حالة خطأ الطلب إلى EAI_CANCELED ويُجرى الإعلام غير المتزامن العادي. لا يمكن إلغاء الطلب إذا كان يُعالج حاليًا؛ في تلك الحالة، يُعالج كما لو أن gai_cancel() لم تُستدعَ أبدًا. إذا كان req NULL، فتُبذل محاولة لإلغاء جميع الطلبات المعلقة التي قامت بها العملية.

قيمة الإرجاع

ترجع الدالة getaddrinfo_a() 0 إذا صُفت جميع الطلبات في قائمة الانتظار بنجاح، أو أحد رموز الخطأ غير الصفرية التالية:

لم تكن الموارد اللازمة لصف طلبات البحث في قائمة الانتظار متاحة. يمكن للتطبيق التحقق من حالة خطأ كل طلب لتحديد أي منها فشل.
نفدت الذاكرة.
mode غير صالح.

ترجع الدالة gai_suspend() 0 إذا أُكمل طلب واحد على الأقل من الطلبات المدرجة. وإلا، فترجع أحد رموز الخطأ غير الصفرية التالية:

انتهت المهلة المعطاة قبل أن يُكمل أي من الطلبات.
لم تُعطَ أي طلبات فعلية للدالة.
قاطعت إشارة الدالة. لاحظ أن هذا الانقطاع قد يكون ناتجًا عن إعلام إشارة لبعض طلبات البحث المكتملة.

يمكن للدالة gai_error() أن ترجع EAI_INPROGRESS لطلب بحث غير مكتمل، أو 0 لبحث أُكمل بنجاح (كما هو موصوف أعلاه)، أو أحد رموز الخطأ التي قد ترجعها getaddrinfo(3)، أو رمز الخطأ EAI_CANCELED إذا أُلغي الطلب صراحةً قبل أن يُكمل.

يمكن للدالة gai_cancel() أن ترجع إحدى هذه القيم:

أُلغي الطلب بنجاح.
لم يُلغَ الطلب.
اكتمل الطلب بالفعل.

ترجم الدالة gai_strerror(3) رموز الخطأ هذه إلى سلسلة نصية مقروءة للبشر، مناسبة للإبلاغ عن الأخطاء.

السمات

للاطلاع على شرح للمصطلحات المستخدمة في هذا القسم، انظر attributes(7).

الواجهة السمة القيمة
getaddrinfo_a(), gai_suspend(), gai_error(), gai_cancel() سلامة الخيوط MT-Safe

المعايير

GNU.

التاريخ

glibc 2.2.3.

صُممت واجهة getaddrinfo_a() على غرار واجهة lio_listio(3).

أمثلة

يُقدَّم مثالان: مثال بسيط يحل عدة طلبات بالتوازي بشكل تزامني، ومثال معقد يُظهر بعض القدرات اللاتزامنية.

مثال تزامني

يحل البرنامج أدناه ببساطة عدة أسماء مضيفين بالتوازي، مما يُعطي تسريعًا مقارنة بحل أسماء المضيفين تسلسليًا باستخدام getaddrinfo(3). يمكن استخدام البرنامج هكذا:


$ ./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

هذا هو الكود المصدري للبرنامج

#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, "Usage: %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() failed: %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() failed: %s\n",
gai_strerror(ret));
exit(EXIT_FAILURE);
}
puts(host);
} else {
puts(gai_strerror(ret));
}
}
exit(EXIT_SUCCESS); }

مثال لاتزامني

يُظهر هذا المثال واجهة أمامية تفاعلية بسيطة لـ getaddrinfo_a(). لم يُوضَّح مرفق الإشعار.

قد تبدو جلسة مثال هكذا:


$ ./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

المصدر البرمجي للبرنامج كما يلي:

#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 n, size_t size) {
void *q;
q = reallocarray(p, n, size);
if (q == NULL && n != 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; } /* Add requests for specified hostnames. */ 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);
}
/* 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 ret;
size_t n;
struct gaicb const **wait_reqs;
wait_reqs = CALLOC(nreqs, const struct gaicb *);
if (wait_reqs == NULL)
err(EXIT_FAILURE, "calloc");
/* 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 (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 ? "Finished" : gai_strerror(ret));
} } /* Cancel specified requests. */ static void cancel_requests(void) {
char *id;
int ret;
size_t 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 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() failed: %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, "Bad command: %c\n", cmd[0]);
break;
}
}
}
exit(EXIT_SUCCESS); }

انظر أيضًا

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

ترجمة

تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.

8 فبراير 2026 صفحات دليل لينكس (لم تصدر بعد)