الاسم
- Provided by: manpages-ar-dev (Version: 4.31.0-1)
- Source: manpages-l10n
- Report a bug
مكتبة البحث عن الأسماء غير المتزامنة (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 له إحدى القيم التالية:
المصفوفة 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_SIGNAL و SIGEV_THREAD، قد يكون من المفيد توجيه sevp->sigev_value.sival_ptr إلى list.
الدالة gai_suspend() تُعلق تنفيذ الخيط المُستدعي، منتظرة اكتمال طلب واحد أو أكثر في المصفوفة list. المعامل n يحدد حجم المصفوفة list. يُحجَز الاستدعاء حتى يحدث أحد التالي:
لا يُعطى إشارة صريحة عن أي طلب أُكمل؛ يجب عليك تحديد أي الطلبات أُكملت بالتكرار مع gai_error() على قائمة الطلبات.
ترجع الدالة gai_error() حالة الطلب req: إما EAI_INPROGRESS إذا لم يُكمل الطلب بعد، أو 0 إذا عُولج بنجاح، أو رمز خطأ إذا تعذر حل الطلب.
تلغي الدالة gai_cancel() الطلب req. إذا أُلغي الطلب بنجاح، فتُضبط حالة خطأ الطلب إلى EAI_CANCELED ويُجرى الإعلام غير المتزامن العادي. لا يمكن إلغاء الطلب إذا كان يُعالج حاليًا؛ في تلك الحالة، يُعالج كما لو أن gai_cancel() لم تُستدعَ أبدًا. إذا كان req NULL، فتُبذل محاولة لإلغاء جميع الطلبات المعلقة التي قامت بها العملية.
ترجع الدالة getaddrinfo_a() 0 إذا صُفت جميع الطلبات في قائمة الانتظار بنجاح، أو أحد رموز الخطأ غير الصفرية التالية:
ترجع الدالة 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.