Scroll to navigation

recv(2) System Calls Manual recv(2)

الاسم

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

المكتبة

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

موجز

#include <sys/socket.h>
ssize_t recv(size_t size;
                 int sockfd, void buf[size], size_t size,
                 int flags);
ssize_t recvfrom(size_t size;
                 int sockfd, void buf[restrict size], size_t size,
                 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, size, flags);

يكافئ


recvfrom(sockfd, buf, size, 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)، ورزم الإنترنت (منذ Linux 2.4.27/2.6.8)، وnetlink (منذ Linux 2.6.22)، ورزم UNIX وكذلك الحزم المتسلسلة (منذ Linux 3.4): إعادة الحجم الحقيقي للحزمة أو الرزمة، حتى عندما كانت أطول من المخزن المؤقت الممرر.
للاستخدام مع مقابس تيار الإنترنت، انظر tcp(7).
يطلب هذا العلم أن تحظر العملية حتى يتم تلبية الطلب بالكامل. ومع ذلك، قد لا يزال الاستدعاء يعيد بيانات أقل من المطلوب إذا تم التقاط إشارة، أو حدث خطأ أو قطع اتصال، أو كانت البيانات التالية المراد استقبالها من نوع مختلف عن تلك المُعادة. ليس لهذا العلم أي تأثير على مقابس الرزم.

recvfrom()

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

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

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

recv()

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


recvfrom(fd, buf, size, flags, NULL, NULL);

recvmsg()

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


struct msghdr {

void *msg_name; /* عنوان اختياري */
socklen_t msg_namelen; /* حجم العنوان */
struct iovec *msg_iov; /* مصفوفة توزيع/تجميع */
size_t msg_iovlen; /* عدد العناصر في msg_iov */
void *msg_control; /* بيانات مساعدة، انظر أدناه */
size_t msg_controllen; /* حجم مخزن البيانات المساعدة */
int msg_flags; /* أعلام على الرسالة المستلمة */ };

يشير حقل 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-2024.

التاريخ

POSIX.1-2001،‏ 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.

29 أكتوبر 2025 صفحات دليل لينكس 6.18