الاسم
- Provided by: manpages-ar-dev (Version: 4.31.0-1)
- Source: manpages-l10n
- Report a bug
مكتبة سي المعيارية (libc، -lc)
#include <sys/types.h> #include <sys/socket.h> #include <netdb.h>
int getaddrinfo(const char *restrict node,
const char *restrict service,
const struct addrinfo *restrict hints,
struct addrinfo **restrict res);
void freeaddrinfo(struct addrinfo *res);
const char *gai_strerror(int errcode);
getaddrinfo(), freeaddrinfo(), gai_strerror():
منذ glibc 2.22:
_POSIX_C_SOURCE >= 200112L
glibc 2.21 وما قبله:
_POSIX_C_SOURCE
بمعطى node و service، اللذان يُعرِّفان مضيف إنترنت وخدمة، تُرجع getaddrinfo() بنية addrinfo واحدة أو أكثر، كل منها يحتوي على عنوان إنترنت يمكن تحديده في استدعاء لـ bind(2) أو connect(2). تدمج دالة getaddrinfo() الوظائف التي توفرها دالتا gethostbyname(3) و getservbyname(3) في واجهة واحدة، ولكن على عكس الدالتين الأخيرتين، فإن getaddrinfo() قابلة لإعادة الدخول وتسمح للبرامج بإزالة التبعيات بين IPv4 و IPv6.
تحتوي بنية addrinfo المستخدمة بواسطة getaddrinfo() على الحقول التالية:
struct addrinfo {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
socklen_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};
يشير معامل hints إلى بنية addrinfo تحدد معايير اختيار بنى عنوان المقبس المُعادة في القائمة المشار إليها بواسطة res. إذا لم يكن hints NULL، فإنه يشير إلى بنية addrinfo تحدد حقولها ai_family و ai_socktype و ai_protocol معايير تحد من مجموعة عناوين المقبس التي تُرجعها getaddrinfo()، كما يلي:
يجب أن تحتوي جميع الحقول الأخرى في البنية المشار إليها بواسطة hints إما على 0 أو مؤشر فارغ، حسب الاقتضاء.
تحديد hints كـ NULL يعادل ضبط ai_socktype و ai_protocol على 0؛ و ai_family على AF_UNSPEC؛ و ai_flags على (AI_V4MAPPED | AI_ADDRCONFIG). (يحدد POSIX قيمًا مبدئية مختلفة لـ ai_flags؛ انظر الملاحظات.) يحدد node إما عنوان شبكة رقمي (لـ IPv4، ترميز الأرقام والنقاط كما تدعمه inet_aton(3)؛ لـ IPv6، تنسيق سلسلة محارف سداسي عشري كما تدعمه inet_pton(3))، أو اسم مضيف شبكة، تُبحث عناوين شبكته وتُحل. إذا احتوى hints.ai_flags على العلم AI_NUMERICHOST، فيجب أن يكون node عنوان شبكة رقمي. يمنع العلم AI_NUMERICHOST أي عمليات بحث عن عنوان مضيف شبكة قد تكون طويلة.
إذا حُدد العلم AI_PASSIVE في hints.ai_flags، وكان node NULL، فإن عناوين المقبس المُعادة ستكون مناسبة لـ bind(2) مقبس سيقبل accept(2) اتصالات. سيحتوي عنوان المقبس المُعاد على "عنوان البدل" (INADDR_ANY لعناوين IPv4، IN6ADDR_ANY_INIT لعنوان IPv6). يُستخدم عنوان البدل بواسطة التطبيقات (عادة الخوادم) التي تنوي قبول اتصالات على أي من عناوين شبكة المضيف. إذا لم يكن node NULL، فإن العلم AI_PASSIVE يُتجاهل.
إذا لم يُضبط العلم AI_PASSIVE في hints.ai_flags، فإن عناوين المقابس المُعادة ستكون مناسبة للاستخدام مع connect(2) أو sendto(2) أو sendmsg(2). إذا كان node NULL، فسيُضبط عنوان الشبكة على عنوان واجهة الاسترجاع (INADDR_LOOPBACK لعناوين IPv4، IN6ADDR_LOOPBACK_INIT لعناوين IPv6)؛ يُستخدم هذا من قبل التطبيقات التي تنوي التواصل مع الأقران العاملين على نفس المضيف.
يُضبط service المنفذ في كل بنية عنوان مُعادة. إذا كانت هذه الوسيطة اسم خدمة (انظر services(5))، فتُترجم إلى رقم المنفذ المقابل. يمكن أيضًا تحديد هذه الوسيطة كرقم عشري، يُحوّل ببساطة إلى ثنائي. إذا كان service NULL، فسيُترك رقم منفذ عناوين المقابس المُعادة غير مهيأ. إذا حُدد AI_NUMERICSERV في hints.ai_flags وكان service ليس NULL، فيجب أن يشير service إلى سلسلة محارف تحتوي على رقم منفذ عددي. يُستخدم هذا العلم لمنع استدعاء خدمة تحليل الأسماء في الحالات التي يُعرف فيها أنها غير مطلوبة.
قد يكون إما node أو service، وليس كلاهما، NULL.
تخصص الدالة getaddrinfo() وتهيئ قائمة مرتبطة من بنى addrinfo، واحدة لكل عنوان شبكة يطابق node و service، مع مراعاة أي قيود يفرضها hints، وتُعيد مؤشرًا إلى بداية القائمة في res. تُربط العناصر في القائمة المرتبطة بواسطة الحقل ai_next.
هناك عدة أسباب قد تجعل القائمة المرتبطة تحتوي على أكثر من بنية addrinfo، منها: المضيف الشبكي متعدد الواجهات، يمكن الوصول إليه عبر بروتوكولات متعددة (مثل AF_INET و AF_INET6)؛ أو أن نفس الخدمة متاحة من أنواع مقابس متعددة (عنوان SOCK_STREAM وآخر SOCK_DGRAM مثلاً). عادةً، يجب على التطبيق محاولة استخدام العناوين بالترتيب الذي أُعيدت به. دالة الفرز المستخدمة داخل getaddrinfo() مُعرّفة في RFC 3484؛ يمكن تعديل الترتيب لنظام معين بتحرير /etc/gai.conf (متاح منذ glibc 2.5).
إذا تضمن hints.ai_flags العلم AI_CANONNAME، فسيُضبط الحقل ai_canonname لأول بنية addrinfo في القائمة المُعادة ليشير إلى الاسم الرسمي للمضيف.
تُهيأ الحقول المتبقية لكل بنية addrinfo مُعادة كما يلي:
إذا تضمن hints.ai_flags العلم AI_ADDRCONFIG، فتُعاد عناوين IPv4 في القائمة المشار إليها بـ res فقط إذا كان النظام المحلي يحتوي على عنوان IPv4 واحد على الأقل مُهيأ، وتُعاد عناوين IPv6 فقط إذا كان النظام المحلي يحتوي على عنوان IPv6 واحد على الأقل مُهيأ. لا يُعتبر عنوان الاسترجاع صالحًا كعنوان مُهيأ في هذه الحالة. هذا العلم مفيد، على سبيل المثال، في الأنظمة التي تعمل بـ IPv4 فقط، لضمان أن getaddrinfo() لا تُعيد عناوين مقابس IPv6 التي ستفشل دائمًا في connect(2) أو bind(2).
إذا حدد hints.ai_flags العلم AI_V4MAPPED، وحُدد hints.ai_family كـ AF_INET6، ولم يُعثر على عناوين IPv6 مطابقة، فتُعاد عناوين IPv6 المعينة من IPv4 في القائمة المشار إليها بـ res. إذا حُدد كل من AI_V4MAPPED و AI_ALL في hints.ai_flags، فتُعاد عناوين IPv6 وعناوين IPv6 المعينة من IPv4 في القائمة المشار إليها بـ res. يُتجاهل AI_ALL إذا لم يُحدد AI_V4MAPPED أيضًا.
تحرر الدالة freeaddrinfo() الذاكرة التي خُصصت للقائمة المرتبطة المخصصة ديناميكيًا res.
بدءًا من glibc 2.3.4، وُسعت getaddrinfo() للسماح بشكل انتقائي بتحويل أسماء المضيفات الواردة والصادرة بشفافية من وإلى تنسيق اسم النطاق المعولم (IDN) (انظر RFC 3490، تعميم أسماء النطاقات في التطبيقات (IDNA)). عُرفت أربعة أعلام جديدة:
تُرجع الدالة getaddrinfo() القيمة 0 عند النجاح، أو أحد رموز الخطأ غير الصفرية التالية:
تُترجم الدالة gai_strerror() رموز الخطأ هذه إلى سلسلة محارف قابلة للقراءة البشرية، مناسبة للإبلاغ عن الأخطاء.
/etc/gai.conf
للاطلاع على شرح للمصطلحات المستخدمة في هذا القسم، انظر attributes(7).
| الواجهة | السمة | القيمة |
| getaddrinfo() | سلامة الخيوط | بيئة محلية آمنة لتعدد الخيوط (MT-Safe) |
| freeaddrinfo(), gai_strerror() | سلامة الخيوط | MT-Safe |
وفقًا لـ POSIX.1، يجب أن يؤدي تحديد hints كـ NULL إلى افتراض ai_flags كـ 0. تفترض مكتبة GNU C بدلاً من ذلك قيمة (AI_V4MAPPED | AI_ADDRCONFIG) لهذه الحالة، حيث تُعتبر هذه القيمة تحسينًا على المواصفات.
POSIX.1-2008.
POSIX.1-2001.
تدعم getaddrinfo() الترميز address%scope-id لتحديد نطاق IPv6 scope-ID.
توضح البرامج التالية استخدام getaddrinfo()، gai_strerror()، freeaddrinfo()، و getnameinfo(3). البرامج هي خادم وعميل صدى لبيانات UDP.
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define BUF_SIZE 500
int
main(int argc, char *argv[])
{
int sfd, s;
char buf[BUF_SIZE];
ssize_t nread;
socklen_t peer_addrlen;
struct addrinfo hints;
struct addrinfo *result, *rp;
struct sockaddr_storage peer_addr;
if (argc != 2) {
fprintf(stderr, "Usage: %s port\n", argv[0]);
exit(EXIT_FAILURE);
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
hints.ai_protocol = 0; /* Any protocol */
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
s = getaddrinfo(NULL, argv[1], &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
/* getaddrinfo() returns a list of address structures.
Try each address until we successfully bind(2).
If socket(2) (or bind(2)) fails, we (close the socket
and) try the next address. */
for (rp = result; rp != NULL; rp = rp->ai_next) {
sfd = socket(rp->ai_family, rp->ai_socktype,
rp->ai_protocol);
if (sfd == -1)
continue;
if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0)
break; /* Success */
close(sfd);
}
freeaddrinfo(result); /* No longer needed */
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not bind\n");
exit(EXIT_FAILURE);
}
/* Read datagrams and echo them back to sender. */
for (;;) {
char host[NI_MAXHOST], service[NI_MAXSERV];
peer_addrlen = sizeof(peer_addr);
nread = recvfrom(sfd, buf, BUF_SIZE, 0,
(struct sockaddr *) &peer_addr, &peer_addrlen);
if (nread == -1)
continue; /* Ignore failed request */
s = getnameinfo((struct sockaddr *) &peer_addr,
peer_addrlen, host, NI_MAXHOST,
service, NI_MAXSERV, NI_NUMERICSERV);
if (s == 0)
printf("Received %zd bytes from %s:%s\n",
nread, host, service);
else
fprintf(stderr, "getnameinfo: %s\n", gai_strerror(s));
if (sendto(sfd, buf, nread, 0, (struct sockaddr *) &peer_addr,
peer_addrlen) != nread)
{
fprintf(stderr, "Error sending response\n");
}
}
}
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define BUF_SIZE 500
int
main(int argc, char *argv[])
{
int sfd, s;
char buf[BUF_SIZE];
size_t size;
ssize_t nread;
struct addrinfo hints;
struct addrinfo *result, *rp;
if (argc < 3) {
fprintf(stderr, "Usage: %s host port msg...\n", argv[0]);
exit(EXIT_FAILURE);
}
/* Obtain address(es) matching host/port. */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_flags = 0;
hints.ai_protocol = 0; /* Any protocol */
s = getaddrinfo(argv[1], argv[2], &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
/* getaddrinfo() returns a list of address structures.
Try each address until we successfully connect(2).
If socket(2) (or connect(2)) fails, we (close the socket
and) try the next address. */
for (rp = result; rp != NULL; rp = rp->ai_next) {
sfd = socket(rp->ai_family, rp->ai_socktype,
rp->ai_protocol);
if (sfd == -1)
continue;
if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
break; /* Success */
close(sfd);
}
freeaddrinfo(result); /* No longer needed */
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not connect\n");
exit(EXIT_FAILURE);
}
/* Send remaining command-line arguments as separate
datagrams, and read responses from server. */
for (size_t j = 3; j < argc; j++) {
size = strlen(argv[j]) + 1;
/* +1 for terminating null byte */
if (size > BUF_SIZE) {
fprintf(stderr,
"Ignoring long message in argument %zu\n", j);
continue;
}
if (write(sfd, argv[j], size) != size) {
fprintf(stderr, "partial/failed write\n");
exit(EXIT_FAILURE);
}
nread = read(sfd, buf, BUF_SIZE);
if (nread == -1) {
perror("read");
exit(EXIT_FAILURE);
}
printf("Received %zd bytes: %s\n", nread, buf);
}
exit(EXIT_SUCCESS);
}
getaddrinfo_a(3), gethostbyname(3), getnameinfo(3), inet(3), gai.conf(5), hostname(7), ip(7)
تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>
هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.
إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.