Scroll to navigation

recv(2) System Calls Manual recv(2)

الاسم

recv، recvfrom، recvmsg - استلام رسالة من مقبس

المكتبة

مكتبة سي المعيارية (libc، -lc)

موجز

#include <sys/socket.h>
ssize_t recv(int sockfd, void buf[.len], size_t len,
                 int flags);
ssize_t recvfrom(int sockfd, void buf[restrict .len], size_t len,
                 int flags,
                 struct sockaddr *_Nullable restrict src_addr,
                 socklen_t *_Nullable restrict addrlen);
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

الوصف

استدعاءات recv() و recvfrom() و recvmsg() تُستخدم لاستقبال رسائل من مقبس. يمكن استخدامها لاستقبال بيانات على كل من المقابس غير المتصلة والموجهة نحو الاتصال. تصف هذه الصفحة أولاً الميزات المشتركة لجميع استدعاءات النظام الثلاثة، ثم تصف الاختلافات بين الاستدعاءات.

الفرق الوحيد بين recv() و read(2) هو وجود flags. مع وسيطة flags صفرية، يكون recv() مكافئًا بشكل عام لـ read(2) (لكن انظر الملاحظات). أيضًا، الاستدعاء التالي


recv(sockfd, buf, len, flags);

يكافئ


recvfrom(sockfd, buf, len, flags, NULL, NULL);

تعيد الاستدعاءات الثلاثة طول الرسالة عند الإكمال الناجح. إذا كانت الرسالة طويلة جدًا بحيث لا تناسب المخزن المؤقت المقدم، قد تُتجاهل البايتات الزائدة اعتمادًا على نوع المقبس الذي تُستقبل منه الرسالة.

إذا لم تكن هناك رسائل متاحة في المقبس، تنتظر استدعاءات الاستقبال وصول رسالة، ما لم يكن المقبس غير محظور (انظر fcntl(2))، وفي هذه الحالة تُعاد القيمة -1 ويُضبط errno على EAGAIN أو EWOULDBLOCK. تعيد استدعاءات الاستقبال عادةً أي بيانات متاحة، حتى المقدار المطلوب، بدلاً من انتظار استلام المقدار الكامل المطلوب.

يمكن للتطبيق استخدام select(2) أو poll(2) أو epoll(7) لتحديد موعد وصول المزيد من البيانات على مقبس.

معامل العلامات (flags)

تُشكل وسيطة flags عن طريق إجراء عملية OR على قيمة واحدة أو أكثر من القيم التالية:

يضبط علم الإغلاق عند التنفيذ لواصف الملف المستلم عبر واصف ملف نطاق UNIX باستخدام عملية SCM_RIGHTS (الموصوفة في unix(7)). هذا العلم مفيد لنفس أسباب علم O_CLOEXEC الخاص بـ open(2).
يفعّل التشغيل غير المحظور؛ إذا كانت العملية ستحظر، يفشل الاستدعاء مع الخطأ EAGAIN أو EWOULDBLOCK. يوفر هذا سلوكًا مشابهًا لتعيين العلم O_NONBLOCK (عبر عملية fcntl(2) F_SETFL)، لكنه يختلف في أن MSG_DONTWAIT هو خيار لكل استدعاء، بينما O_NONBLOCK هو إعداد على وصف الملف المفتوح (انظر open(2))، مما سيؤثر على جميع الخيوط في العملية المستدعية بالإضافة إلى العمليات الأخرى التي تحمل واصفات ملفات تشير إلى نفس وصف الملف المفتوح.
يحدد هذا العلم أنه يجب استقبال الأخطاء المُصطفة من قائمة انتظار أخطاء المقبس. يُمرر الخطأ في رسالة مساعدة بنوع يعتمد على البروتوكول (لـ IPv4 IP_RECVERR). يجب على المستخدم توفير مخزن مؤقت بحجم كافٍ. انظر cmsg(3) و ip(7) لمزيد من المعلومات. يُمرر حمولة الحزمة الأصلية التي تسببت في الخطأ كبيانات عادية عبر msg_iovec. يُمرر عنوان الوجهة الأصلي للرزمة التي تسببت في الخطأ عبر msg_name.
يُقدم الخطأ في بنية sock_extended_err:

#define SO_EE_ORIGIN_NONE    0
#define SO_EE_ORIGIN_LOCAL   1
#define SO_EE_ORIGIN_ICMP    2
#define SO_EE_ORIGIN_ICMP6   3
struct sock_extended_err
{

uint32_t ee_errno; /* Error number */
uint8_t ee_origin; /* Where the error originated */
uint8_t ee_type; /* Type */
uint8_t ee_code; /* Code */
uint8_t ee_pad; /* Padding */
uint32_t ee_info; /* Additional information */
uint32_t ee_data; /* Other data */
/* More data may follow */ }; struct sockaddr *SO_EE_OFFENDER(struct sock_extended_err *);

يحتوي ee_errno على رقم errno للخطأ المُصطف. ee_origin هو رمز الأصل لمكان نشأة الخطأ. الحقول الأخرى خاصة بالبروتوكول. تعيد الماكرو SO_EE_OFFENDER مؤشرًا إلى عنوان كائن الشبكة حيث نشأ الخطأ، معطى مؤشرًا إلى الرسالة المساعدة. إذا كان هذا العنوان غير معروف، يحتوي عضو sa_family من sockaddr على AF_UNSPEC والحقول الأخرى من sockaddr غير معرفة. يُمرر حمولة الحزمة التي تسببت في الخطأ كبيانات عادية.
بالنسبة للأخطاء المحلية، لا يُمرر أي عنوان (يمكن التحقق من ذلك باستخدام عضو cmsg_len من cmsghdr). لاستقبالات الأخطاء، يُضبط علم MSG_ERRQUEUE في msghdr. بعد تمرير خطأ، يُعاد توليد خطأ المقبس المعلق بناءً على الخطأ المُصطف التالي وسيُمرر في عملية المقبس التالية.
يطلب هذا العلم استقبال بيانات خارج النطاق التي لن تُستقبل في تيار البيانات العادي. تضع بعض البروتوكولات البيانات المعجلة في رأس قائمة انتظار البيانات العادية، وبالتالي لا يمكن استخدام هذا العلم مع هذه البروتوكولات.
يتسبب هذا العلم في إعادة عملية الاستقبال للبيانات من بداية قائمة انتظار الاستقبال دون إزالة تلك البيانات من القائمة. وبالتالي، سيعيد استدعاء استقبال لاحق نفس البيانات.
للمقابس الخام (AF_PACKET)، ومخططات بيانات الإنترنت (منذ لينكس 2.4.27/2.6.8)، وnetlink (منذ لينكس 2.6.22)، ومخططات بيانات UNIX بالإضافة إلى الحزم المتسلسلة (منذ لينكس 3.4): إعادة الطول الحقيقي للحزمة أو مخطط البيانات، حتى عندما كان أطول من المخزن المؤقت الممرر.
للاستخدام مع مقابس تيار الإنترنت، انظر tcp(7).
يطلب هذا العلم أن تحظر العملية حتى يتم تلبية الطلب بالكامل. ومع ذلك، قد لا يزال الاستدعاء يعيد بيانات أقل من المطلوب إذا تم التقاط إشارة، أو حدث خطأ أو قطع اتصال، أو كانت البيانات التالية المراد استقبالها من نوع مختلف عن تلك المُعادة. ليس لهذا العلم أي تأثير على مقابس الرزم.

recvfrom()

تضع recvfrom() الرسالة المستلمة في المخزن المؤقت buf. يجب على المستدعي تحديد حجم المخزن المؤقت في len.

إذا كانت src_addr غير NULL، وكان البروتوكول الأساسي يوفر عنوان مصدر الرسالة، يتم وضع عنوان المصدر هذا في المخزن المؤقت الذي تشير إليه src_addr. في هذه الحالة، تكون addrlen معلمة قيمة-نتيجة. قبل الاستدعاء، يجب تهيئتها بحجم المخزن المؤقت المرتبط بـ src_addr. عند العودة، يحدّث addrlen ليحتوي على الحجم الفعلي لعنوان المصدر. ًيُقتطع العنوان المُرجع إذا كان المخزن المؤقت المُقدّم صغيرًا جدًّا؛ وفي هذه الحالة، سيعيد addrlen قيمة أكبر من تلك التي تم تزويدها للاستدعاء.

إذا لم يكن المستدعي مهتمًا بعنوان المصدر، فيجب تحديد src_addr و addrlen كقيمة NULL.

recv()

عادةً ما يُستخدم استدعاء recv() فقط على مقبس موصل (انظر connect(2)). وهو مكافئ للاستدعاء:


recvfrom(fd, buf, len, flags, NULL, 0);

recvmsg()

يستخدم استدعاء recvmsg() بنية msghdr لتقليل عدد الوسائط المقدمة مباشرة. تُعرف هذه البنية كما يلي في <sys/socket.h>:


struct msghdr {

void *msg_name; /* Optional address */
socklen_t msg_namelen; /* Size of address */
struct iovec *msg_iov; /* Scatter/gather array */
size_t msg_iovlen; /* # elements in msg_iov */
void *msg_control; /* Ancillary data, see below */
size_t msg_controllen; /* Ancillary data buffer len */
int msg_flags; /* Flags on received message */ };

يشير حقل msg_name إلى مخزن مؤقت مخصص من قبل المستدعي يُستخدم لإعادة عنوان المصدر إذا كان المقبس غير موصول. يجب على المستدعي تعيين msg_namelen إلى حجم هذا المخزن قبل هذا الاستدعاء؛ عند العودة من استدعاء ناجح، سيحتوي msg_namelen على طول العنوان المعاد. إذا لم يحتاج التطبيق إلى معرفة عنوان المصدر، يمكن تحديد msg_name كـ NULL.

تصف الحقول msg_iov و msg_iovlen مواقع التوزيع والتجميع، كما نوقش في readv(2).

حقل msg_control، الذي له طول msg_controllen، يشير إلى مخزن مؤقت لرسائل أخرى متعلقة بالتحكم في البروتوكول أو بيانات مساعدة متنوعة. عند استدعاء recvmsg()، يجب أن يحتوي msg_controllen على طول المخزن المؤقت المتاح في msg_control؛ عند العودة من استدعاء ناجح سيحتوي على طول تسلسل رسائل التحكم.

الرسائل تكون بالشكل:


struct cmsghdr {

size_t cmsg_len; /* عدد بايتات البيانات، بما في ذلك الرأس
(النوع هو socklen_t في POSIX) */
int cmsg_level; /* البروتوكول المصدر */
int cmsg_type; /* نوع خاص بالبروتوكول */ /* يتبعه
unsigned char cmsg_data[]; */ };

يجب الوصول إلى البيانات المساعدة فقط من خلال وحدات الماكرو المعرفة في cmsg(3).

كمثال، تستخدم لينكس آلية البيانات المساعدة هذه لتمرير الأخطاء الموسعة، خيارات IP، أو واصفات الملفات عبر مقابس نطاق UNIX. لمزيد من المعلومات حول استخدام البيانات المساعدة في نطاقات المقابس المختلفة، انظر unix(7) و ip(7).

يتم تعيين حقل msg_flags في msghdr عند عودة recvmsg(). يمكن أن يحتوي على عدة أعلام:

يشير إلى نهاية السجل؛ البيانات المعادة أكملت سجلًا (يُستخدم عمومًا مع مقابس من النوع SOCK_SEQPACKET).
يشير إلى أن الجزء الخلفي من مخطط البيانات تم تجاهله لأن مخطط البيانات كان أكبر من المخزن المقدم.
يشير إلى أن بعض بيانات التحكم تم تجاهلها بسبب نقص المساحة في المخزن للبيانات المساعدة.
يُعاد للإشارة إلى أن بيانات عاجلة أو خارج النطاق تم استلامها.
يشير إلى أنه لم يتم استلام أي بيانات ولكن خطأ موسع من قائمة أخطاء المقبس.
يشير إلى أن MSG_CMSG_CLOEXEC تم تحديده في وسيطة flags لـ recvmsg().

قيمة الإرجاع

تُعيد هذه الاستدعاءات عدد البايتات المستلمة، أو -1 إذا حدث خطأ. في حالة حدوث خطأ، يتم تعيين errno للإشارة إلى الخطأ.

عندما يقوم نظير مقبس التدفق بإغلاق منظم، ستكون القيمة المُعادة 0 (الإرجاع التقليدي "نهاية الملف").

تسمح مقابس مخططات البيانات في مجالات مختلفة (مثل مجالي UNIX والإنترنت) بمخططات بيانات بطول صفري. عند استلام مثل هذا المخطط، تكون القيمة المعادة 0.

قد تُعاد القيمة 0 أيضًا إذا كان عدد البايتات المطلوب استلامها من مقبس تدفق هو 0.

الأخطاء

هذه بعض الأخطاء القياسية التي تولدها طبقة المقبس. قد تُولد أخطاء إضافية وتُعاد من وحدات البروتوكول الأساسية؛ راجع صفحات دليلها.

المقبس مُعلّم كغير محظور وعملية الاستقبال ستحظر، أو ضُبط مهلة استقبال وانتهت المهلة قبل استلام البيانات. يسمح POSIX.1 بإرجاع أي من الخطأين لهذه الحالة، ولا يتطلب أن تكون هذه الثوابت بنفس القيمة، لذا يجب على التطبيق المحمول التحقق من كلا الاحتمالين.
الوسيطة sockfd هي واصف ملف غير صالح.
رفض مضيف بعيد السماح باتصال الشبكة (عادةً لأنه لا يشغل الخدمة المطلوبة).
مؤشرات المخزن المؤقت للاستقبال تشير إلى خارج مساحة عنوان العملية.
قُطعت عملية الاستقبال بتسليم إشارة قبل توفر أي بيانات؛ انظر signal(7).
مُرر معامل غير صالح.
تعذر تخصيص ذاكرة لـ recvmsg().
المقبس مرتبط ببروتوكول موجه للاتصال ولم يُوصل (انظر connect(2) و accept(2)).
واصف الملف sockfd لا يشير إلى مقبس.

الإصدارات

وفقًا لـ POSIX.1، يجب أن يكون حقل msg_controllen في بنية msghdr من النوع socklen_t، وحقل msg_iovlen من النوع int، لكن glibc حاليًا يكتب كليهما كـ size_t.

المعايير

POSIX.1-2008.

التاريخ

POSIX.1-2001،‏ 4.4BSD (ظهر أولاً في 4.2BSD).

يصف POSIX.1 فقط الأعلام MSG_OOB و MSG_PEEK و MSG_WAITALL.

ملاحظات

إذا كان هناك مخطط بيانات بطول صفري معلق، فإن read(2) و recv() مع وسيطة flags بقيمة صفر توفر سلوكًا مختلفًا. في هذه الحالة، لا تأثير لـ read(2) (يبقى مخطط البيانات معلقًا)، بينما تستهلك recv() مخطط البيانات المعلق.

انظر recvmmsg(2) للحصول على معلومات حول استدعاء نظام خاص بلينكس يمكن استخدامه لاستقبال مخططات بيانات متعددة في استدعاء واحد.

أمثلة

مثال على استخدام recvfrom() موضح في getaddrinfo(3).

انظر أيضًا

fcntl(2), getsockopt(2), read(2), recvmmsg(2), select(2), shutdown(2), socket(2), cmsg(3), sockatmark(3), ip(7), ipv6(7), socket(7), tcp(7), udp(7), unix(7)

ترجمة

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

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

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

2 مايو 2024 صفحات دليل لينكس 6.9.1